如何在 Flask-SqlAlchemy 中使用子查询?

vik*_*kin 5 sqlalchemy subquery flask flask-sqlalchemy

query_1 = db\\\n    .Query([UserModel, func.count(FriendModel.friend_id)])\\\n    .select_from(UserModel)\\\n    .outerjoin(FriendModel, and_(UserModel.id==FriendModel.user_id))\\\n    .group_by(FriendModel.user_id)\n  s_1 = query_1.subquery(\'s_1\')\n  print s_1.c.id\n  query_2 = db\\\n    .Query(FriendModel)\\\n    .select_from(FriendModel)\\\n    .outerjoin(s_1, FriendModel.user_id==s_1.c.id)\n
Run Code Online (Sandbox Code Playgroud)\n\n

帮助将两个查询放在一起。\n https://gist.github.com/vlikin/17d53440eeef7f4147b2

\n\n
I receive such errors:\nInvalidRequestError: SQL expression, column, or mapped entity expected - got \'[<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f2e28e1b810>, <sqlalchemy.sql.functions.count at 0x7f2e236c3ed0; count>]\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者

\n\n
AttributeError: Neither \xe2\x80\x98count\xe2\x80\x99 object nor \xe2\x80\x98Comparator\xe2\x80\x99 object has an attribute \xe2\x80\x98_autoflush\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n\n

另外,由于 db.Query 而不是 db.session.query,我遇到了问题。我想使用 db.Query 因为它有分页:)

\n\n

谢谢。

\n

zwi*_*ier 3

我遇到了完全相同的问题。

\n\n

我对这个问题的解决方案是直接使用db.session.query并创建一个新的flask_sqlalchemy.Pagination. 该子类包含一个允许我从任何查询创建Pagination对象的方法。

\n\n
from flask import abort\nfrom flask_sqlalchemy import Pagination as _Pagination\n\nclass Pagination(_Pagination):\n    """Extend Pagination class to let us construct it from any BaseQuery."""\n    @classmethod\n    def from_query(cls, query, page, per_page, error_out=True):\n        """Returns `per_page` items from page `page`.  By default it will\n        abort with 404 if no items were found and the page was larger than\n        1.  This behavor can be disabled by setting `error_out` to `False`.\n\n        This is basically a copy of flask_sqlalchemy.Query.paginate()\n\n        Returns an :class:`Pagination` object.\n        """\n        if error_out and page < 1:\n            abort(404)\n        items = query.limit(per_page).offset((page - 1) * per_page).all()\n        if not items and page != 1 and error_out:\n            abort(404)\n\n        # No need to count if we\'re on the first page and there are fewer\n        # items than we expected.\n        if page == 1 and len(items) < per_page:\n            total = len(items)\n        else:\n            total = query.order_by(None).count()\n\n        return cls(query, page, per_page, total, items)\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在根据以下代码片段使用它:

\n\n
query = db.session.query(\xe2\x80\xa6)\npagination = Pagination.from_query(query, page, 20)\n
Run Code Online (Sandbox Code Playgroud)\n\n

首先的问题是,Pagination从 a 创建 -object 的主要逻辑db.Query不是 Pagination 类的一部分,而是在db.Query.paginate().

\n