Django查询集按ISO周号过滤

时间:2012-05-09 14:22:46

标签: python django date filter iso

我有一个包含datefield的模型。我正在尝试获取包含当前周的模型的查询集(从星期一开始)。

因为Django datefield包含简单的datetime.date模型,我假设使用.isocalendar()进行过滤。从逻辑上讲,这正是我想要的,没有经过当前工作日的额外比较和计算。

所以我想要做的就是强制.filter语句在这个逻辑中表现:

if model.date.isocalendar()[2] == datetime.date.today().isocalendar()[2]
    ...

然而如何在filter语句中编写它? .filter(model__date__isocalendar=datetime.date.today().isocalendar())会给出错误的结果(与今天而不是本周相比)。

挖掘真实http://docs.python.org/library/datetime.html我没有注意到任何其他工作日选项...

请注意文档:

  

date.isocalendar()返回3元组,(ISO年份,ISO周编号,ISO   工作日)。

更新

虽然我不喜欢使用范围的解决方案但它是最好的选择。 但是在我的情况下,我创建了一个标记本周开始的变量,只是看起来更大或相等的值,因为如果我正在寻找本周的匹配。在给出周数的情况下需要两端。

today = datetime.date.today()
monday = today - datetime.timedelta(days=today.weekday())

... \
.filter(date__gte=monday)

4 个答案:

答案 0 :(得分:8)

你无法做到这一点。请记住,这不仅仅是Python支持的问题,Django必须将过滤器传递给数据库,并且数据库不支持这种复杂的日期计算。但可以使用__range,其中包含开始日期和结束日期。

答案 1 :(得分:1)

(此答案仅适用于postgres,但可能适用于其他数据库。)

针对此问题的快速而优雅的解决方案是定义这两个custom transformers

from django.db import models
from django.db.models.lookups import DateTransform

@models.DateTimeField.register_lookup
class WeekTransform(DateTransform):
    lookup_name = 'week'


@models.DateTimeField.register_lookup
class ISOYearTransform(DateTransform):
    lookup_name = 'isoyear'

现在您可以按周查询:

from django.utils.timezone import now
year, week, _ = now().isocalendar()

MyModel.objects.filter(created__isoyear=year, created__week=week)

在幕后,Django DateTransform对象使用postgres EXTRACT function,支持weekisoyear

答案 2 :(得分:1)

ExtractWeek已在Django 1.11中引入,用于基于isoweek编号进行过滤。

对于Django 1.10及更低版本,以下解决方案适用于在postgres数据库上按iso编号过滤:

from django.db.models.functions import Extract
from django.db import models
@models.DateTimeField.register_lookup
class ExtractWeek(Extract):
    lookup_name = 'week'

现在查询如下

queryset.annotate(week=ExtractWeek('date'))\
            .filter(week=week_number)

答案 3 :(得分:0)

比使用Amit在他的答案中提到的Extract函数更简单的方法是使用Django 1.11中添加的__week field lookup,因此您可以简单地做到:

.filter(model__date__week=datetime.date.today().isocalendar()[1])