Flask-SqlAlchemy 按日期时间的时间段过滤

Flask-SqlAlchemy Filtering by time section of datetime

我希望使用 Flask-SQlAlchemy 按 Flask-Admin 中日期时间列的时间部分进行过滤。

我目前的尝试是:

class BaseTimeBetweenFilter(filters.TimeBetweenFilter):
    def apply(self, query, value, alias=None):
        return query.filter(cast(Doctor.datetime, Time) >= value[0],
              cast(Doctor.datetime, Time) <= value[1]).all()

我已经显示了时间选择器,如果显示的话

print (value[0])

print (value[1])

它按预期打印出输入的时间。但是查询不起作用。

admin-panel_1 | response = self.full_dispatch_request()

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1641, in full_dispatch_request

admin-panel_1 | rv = self.handle_user_exception(e)

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1544, in handle_user_exception

admin-panel_1 | reraise(exc_type, exc_value, tb)

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask/_compat.py", line 33, in reraise

admin-panel_1 | raise value

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1639, in full_dispatch_request

admin-panel_1 | rv = self.dispatch_request()

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask/app.py", line 1625, in dispatch_request

admin-panel_1 | return self.view_functionsrule.endpoint

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask_admin/base.py", line 69, in inner

admin-panel_1 | return self._run_view(f, *args, **kwargs)

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask_admin/base.py", line 368, in _run_view

admin-panel_1 | return fn(self, *args, **kwargs)

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask_admin/model/base.py", line 1818, in index_view

admin-panel_1 | view_args.search, view_args.filters)

admin-panel_1 | File "/usr/local/lib/python3.5/dist-packages/flask_admin/contrib/sqla/view.py", line 975, in get_list

admin-panel_1 | count = count_query.scalar() if count_query else None

admin-panel_1 | AttributeError: 'list' object has no attribute 'scalar'

此外,我从 sqlalchemy 导入了 Time 和 Cast,这样可以吗,还是我应该从 flask-sqlalchemy 获取它?

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Time, cast

Flask-Admin 通过连接表、应用过滤器和排序来构建查询。在完成所有这些过程后,它会调用查询本身并获取结果。

您的 apply 方法应该 return sqlalchemy.orm.query.Query 实例作为它作为 query 参数获得的实​​例。当您添加 .all() 方法时,将调用此查询并获得查询结果列表。从结果值中删除 .all() 调用,您的过滤器应该可以工作:

class BaseTimeBetweenFilter(filters.TimeBetweenFilter):
    def apply(self, query, value, alias=None):
        return query.filter(
            cast(Doctor.datetime, Time) >= value[0],
            cast(Doctor.datetime, Time) <= value[1]
        )

导入的来源并不重要。 flask_sqlalchemy.SQLAlchemy 实例包含与 sqlalchemy 相同的对象:

>>> from flask_sqlalchemy import SQLAlchemy
>>> db = SQLAlchemy()
>>> db.Time
<class 'sqlalchemy.sql.sqltypes.Time'>
>>> db.cast
<function cast at 0x7f60a3e89c80>
>>> from sqlalchemy import Time, cast
>>> Time
<class 'sqlalchemy.sql.sqltypes.Time'>
>>> cast
<function cast at 0x7f60a3e89c80>
>>> db.cast == cast and db.Time == Time
True