12

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

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

所以我想做的基本上是强制.filter声明在这个逻辑中表现:

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

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

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

文档中的注释:

date.isocalendar() 返回一个三元组,(ISO 年、ISO 周数、ISO 工作日)。

更新:

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

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

... \
.filter(date__gte=monday)
4

4 回答 4

9

你将无法做到这一点。请记住,这不仅仅是 Python 支持什么的问题,Django 必须将过滤器传递给数据库,而数据库不支持如此复杂的日期计算。但是,您可以__range与开始日期和结束日期一起使用。

于 2012-05-09T14:35:06.847 回答
4

Extract比使用Amit 在他的回答中提到的函数更简单的是使用 Django 1.11 中添加的__week字段查找,因此您可以简单地执行以下操作:

.filter(model__date__week=datetime.date.today().isocalendar()[1])
于 2018-11-27T08:49:28.397 回答
2

ExtractWeek 已在 Django 1.11 中引入,用于基于等周数进行过滤。

对于 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)
于 2016-11-26T16:00:16.470 回答
1

(这个答案应该只适用于 postgres,但可能适用于其他数据库。)

这个问题的一个快速而优雅的解决方案是定义这两个自定义转换器:

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)

在幕后,DjangoDateTransform对象使用了 postgresEXTRACT函数,它支持weekisoyear.

于 2016-05-01T15:03:46.650 回答