带有date和.isocalendar()的SQLAlchemy func问题

时间:2015-05-04 12:10:07

标签: python sqlite date datetime sqlalchemy

我有一个表,用于存储用户提交的任务,并带有时间戳。我想写一个查询,根据提交时间返回某些行(是这一天/周/月......)。

为了检查它是否在本周提交,我想使用date.isocalendar()[1]功能。问题是,我的时间戳是datetime s,所以我需要将它们转换为date s。

使用func: filter(func.date(Task.timestamp) == datetime.date(datetime.utcnow())) 工作正常。

但我需要date对象的isocalendar()方法,所以我试试

filter(func.date(Task.timestamp).isocalendar()[1]==datetime.date(datetime.utcnow()).isocalendar()[1])

并且它没有用,我得到AttributeError: Neither 'Function' object nor 'Comparator' object has an attribute 'isocalendar'

如果我做一个简单的查询并尝试datetime.date(task.timestamp).isocalendar()[1]它可以正常工作。

如何在查询的过滤器中使用它?

3 个答案:

答案 0 :(得分:1)

理解和调试sqlalchemy查询时的经验法则总是要考虑 - “它在SQL中的外观如何?”

isocalendar()是一个python函数,sqlalchemy查询过滤器被编译为SQL。而且,isocalendar()返回一个元组 - 虽然渲染元组比较可能是SQL,但它的价值更大。你应该比较标量并找到适合你的sql日期函数。

似乎你想要比较周数,所以这样的事情应该可以解决问题:

filter(func.week(Task.timestamp)==datetime.utcnow().isocalendar()[1])

答案 1 :(得分:0)

你能试试sqlalchemy.extract(func.date('year', Task.timestamp)) == ...吗?

答案 2 :(得分:0)

您不能将纯Python函数与在SQL后端执行的函数混合使用。从您的代码看,您似乎正在尝试过滤iso week。一种方法是将数据库中的所有内容加载到内存中并在那里执行过滤。显然,在大多数情况下,它远没有效率。

另一种方法是使用SQL函数,sqlalchemy将为您调用。在MySQL上看起来您需要的功能是weekofyear,因此您的过滤器可能类似于以下内容:

_utcnow = datetime.utcnow().date()
_isoweek = _utcnow.isocalendar()[1]

q = db.session.query(...)
# ...
q = q.filter(db.func.weekofyear(Task.timestamp) == _isoweek)