【问题标题】:How to annotate a queryset with the difference between today & a DateField using ExpressionWrapper如何使用 ExpressionWrapper 用今天和 DateField 之间的差异来注释查询集
【发布时间】:2019-12-26 13:32:51
【问题描述】:

我正在尝试基于 DateField 对查询集进行注释,如图所示。

我使用的是 Django 版本 1.8.12 和 MYSQL 版本 5.6.40。

尝试关注How to annotate a queryset with number of days since creation,但这里是 DateTimeField。下面的 cmets 说“将其更改为 Value(now.date(), DateField()) - F('creation_date__date'), 不起作用”

型号代码如下:

class Holding(models.Model):
    trans_date = models.DateField(_("Trans. Date"), null=False)
    ...

给出错误持续时间的注释查询如下所示:

today = timezone.now().date()
testqs = Holding.objects.filter(id=1)
myqs = testqs.annotate(duration = ExpressionWrapper( Value(today, DateField()) - F('trans_date'), output_field=DurationField()))

当我尝试打印时,在此期间我得到的只是无。打印差异以供参考。

for i in myqs:
    print i.duration, '-', today-i.trans_date

None - 1224 days, 0:00:00
None - 1206 days, 0:00:00
None - 1144 days, 0:00:00
None - 1051 days, 0:00:00
None - 1045 days, 0:00:00

我希望持续时间是一个 timedelta 值,其中今天和 trans_date 之间的差异而不是 None。

【问题讨论】:

  • 我无法重现您的问题。您的查询应该有效。我用DateField 在我的模型上尝试了完全相同的查询,当我打印duration 注释时它返回“9661 天,0:00:00”。
  • 你能告诉我你的 Django 和 MySql 版本吗?我已经在不同的模型上进行了尝试,如下所示,但仍然没有得到正确的持续时间值。
  • Django 1.11,postgreSQL 9.6
  • 我了解您有不同的版本,但 Django 1.8 已经支持 ExpressionWrapper,不知道为什么它不适合您。但是,是的,可能是您的特定设置的问题。
  • 另外我不能提出替代查询,我能想到的所有替代方法都只在 Django 1.11 或 2.2 中支持。但尚不清楚这是 MySQL 还是 Django 问题。

标签: django django-queryset annotate datefield


【解决方案1】:

这对我有用(带有 SQLite 的 Django 2.2.20):

import datetime as dt
from django import models
from django.db.models import F, ExpressionWrapper, fields
from django.db.models.functions import Now, TruncDate

class Test(models.Model):
    due_date=models.DateField(null=True, blank=True, default=dt.date.today)

due_in = ExpressionWrapper(
        F('due_date') - TruncDate(Now()),
        output_field=fields.DurationField())
qs = Test.objects.annotate(due_in=due_in)  # due_in will be dt.timedelta

在某些具有原生 DurationField 支持的数据库中,我相信您可以执行以下操作将天数提取为 int 字段,这将允许分组等, 但这在 SQLite 中不受支持。

due_in_days = ExtractDay(due_in)
qs = Test.objects.annotate(due_in_days=due_in_days)  # result is int

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 2013-01-11
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    相关资源
    最近更新 更多