2015-05-04 76 views
0

我有一个表,存储用户提交的任务与时间戳。我想编写一个查询,根据它们提交的时间(是今天/每周/每月...)返回特定的行。SQLAlchemy func问题与日期和.isocalendar()

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

使用功能: 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]它工作正常。

如何让它在查询过滤器中工作?

回答

0

你可以试试sqlalchemy.extract(func.date('year', Task.timestamp)) == ...

+0

'func.extract( '周',func.date(Task.timestamp))== ... '工作,但它返回一个比iso格式少的数据(根据isocalendar(),今天是第19周,而根据这是第18天)。我找不到任何文档,这是否只是一个区别,因为一个从0开始计数,另一个从1开始计数,还是其他的?如果它的前者,我想从ISO格式减去1将解决问题? – lacer

1

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

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

好像你正在寻找比较星期数,因此这样的事情应该做的伎俩:

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

这似乎没有工作,即使我添加了[模式](https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_week)作为'func.week'里面的参数。它表示没有'week'这样的函数 – lacer

+0

你在func上调用的任何函数都会直接被转换为SQL,所以你的数据库应该有它。我不知道你在用什么,但你标记为mysql,而mysql有它:https://dev.mysql.com/doc/refman/5。5/en/date-and-time-functions.html#function_week – letitbee

+0

是的,那是我的错,我实际上使用SQLite,所以这就是为什么它不工作。 – lacer

0

你不能用的那些在SQL后端执行混合纯Python功能。从你的代码看起来你正试图在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) 
+0

是的,那正是我想要做的。另一方面,它会抛出一个'sqlalchemy.exc.OperationalError:(OperationalError)no such function:weekofyear'SELECT ...'我输入'func',也许我错过了别的东西呢? – lacer

+0

尝试使用'db.func.week(Task.timestamp,3)'代替它,也许它已在更高版本的MySQL中引入(并且我没有太多关于此RDBMS的知识) – van