我有一个包含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)
答案 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,支持week
和isoyear
。
答案 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])