sqlalchemy分页

时间:2011-06-08 17:07:54

标签: python sqlalchemy

我正在使用flask和sqlalchemy构建一个REST应用程序,我遇到了一个问题。我想查询所有用户的账簿数量。每个用户都有很多书,所以我的查询应该返回每个用户在结果集中拥有的书籍数量。

//      Models
class User( object ):
    __tablename__ = 'user'

class Book( object ):
    __tablename__ = 'book'

//      Metadata
users_table = Table( 'user', metadata,
    Column( 'id', Integer, primary_key = True ),
    Column( 'username', String( 50 ), unique = True )
)

books_table = Table( 'book', metadata,
    Column( 'id', Integer, primary_key = True ),
    Column( 'title', String( 50 ) ),
    Column( 'user_id', Integer, ForeignKey( 'user.id' ) )
)

//      Mappers
mapper( User, users_table, properties = {
    'booksCount': column_property( 
        select( 
            [func.count( books_table.c.id )],
            books_table.c.user_id == users_table.c.id
        ).label( 'booksCount' )
    ),
    'books' : relationship( Book )
} )

mapper( Book, books_table, properties = {
    'user': relationship( User )
} )

如果我想查询所有用户它的工作正常并带回相关的'booksCount'结果,但如果我想更深入,让我们说只查询'booksCount'大于4的用户它会变得复杂因为在应用限制/偏移之前我还需要知道总结果计数才能使我的分页工作。

//  this works
rows = User.query
totalRows = rows.count ()
users = rows.limit( 50 ).offset( 0 ).all()

for user in users:
    ...

//  this throws an error
rows = User.query.having('booksCount>4')
totalRows = rows.count ()
users = rows.limit( 50 ).offset( 0 ).all()

第二个示例中出现此失败的原因是因为totalRows = rows.count ()创建了第二个查询来计算第一个结果:SELECT count(1) AS count_1 FROM user但是当having插入查询时它会更改为{ {1}}由于在第二次查询中从未选择booksCount,因此显示错误。

那么如何在应用了SELECT count(1) AS count_1 FROM user having booksCount>4子句的select中提取总行数呢?

感谢。

2 个答案:

答案 0 :(得分:2)

这实际上是一个sql语法错误。 having子句仅在包含group by子句时使用,并且仅过滤聚合结果。您需要的是一个简单的where条款:

rows = User.query.filter(User.booksCount > 4)

作为旁注:请按照python标准执行您的代码,例如: User.books_count

答案 1 :(得分:0)

我会用相同情况下的每个其他人的解决方案回答我自己的问题。如果您使用的是ubuntu并从repo安装了sqlalchemy,请将其卸载并转至sqlalchemy网站并按照其说明进行安装。新版本(0.7.1 atm)修复了这个错误。

Ubuntu附带0.6.4版本。