新版本 Django 中 DateModifierNode 的替代品是啥

Posted

技术标签:

【中文标题】新版本 Django 中 DateModifierNode 的替代品是啥【英文标题】:What is the replacement for DateModifierNode in new versions of Django新版本 Django 中 DateModifierNode 的替代品是什么 【发布时间】:2016-12-06 18:43:09 【问题描述】:

我想根据模型的两个字段进行查询,一个日期,一个整数偏移量,用作时间增量

model.objects.filter(last_date__gte=datetime.now()-timedelta(days=F('interval')))

不可行,因为 F() 表达式不能传递到 timedelta 中

稍微挖掘一下,我发现了DateModifierNode - 虽然它似乎在这个提交中被删除了:https://github.com/django/django/commit/cbb5cdd155668ba771cad6b975676d3b20fed37b(来自这个现在已经过时的SO问题Django: Using F arguments in datetime.timedelta inside a query)

提交提到:

.dates() 查询是通过使用自定义 Query、QuerySet、 和编译器类。而是通过使用表达式和 数据库转换器 API。

这听起来很明智,而且应该仍然有一个快速简单的方法 - 但我一直在寻找如何做到这一点太久了 - 有人知道答案吗?

【问题讨论】:

您不必更改模型结构并手动添加。参考this。 【参考方案1】:

在 Django 1.10 中有更简单的方法可以做到这一点,但您需要稍微更改模型:使用 DurationField。我的模型如下:

class MyModel(models.Model):

    timeout = models.DurationField(default=86400 * 7)  # default: week
    last = models.DateTimeField(auto_now_add=True)

查找lastnow 之前减去timeout 的对象的查询是:

MyModel.objects.filter(last__lt=datetime.datetime.now()-F('timeout'))

【讨论】:

未对此进行测试 - 但假设您有 ;) 看起来是一个更好的解决方案!即将升级django【参考方案2】:

啊,来自文档的回答:https://docs.djangoproject.com/en/1.9/ref/models/expressions/#using-f-with-annotations

from django.db.models import DateTimeField, ExpressionWrapper, F

Ticket.objects.annotate(
    expires=ExpressionWrapper(
        F('active_at') + F('duration'), output_field=DateTimeField()))

这应该使我的原始查询看起来像

model.objects.annotate(new_date=ExpressionWrapper(F('last_date') + F('interval'), output_field=DateTimeField())).filter(new_date__gte=datetime.now())

【讨论】:

对于F('last_date') + F('interval') 非常可能并且输出是日期时间字段?和timedelta(days=interval)一样的天数增加? 从日期中减去一个数字对我不起作用,因为它不被认为是天数的减法。我正在使用 mysql

以上是关于新版本 Django 中 DateModifierNode 的替代品是啥的主要内容,如果未能解决你的问题,请参考以下文章

Django新版本3.1,设置文件有一些变化

最新版Django用视图使用问题

Django,可以运行两个不同的版本吗?

配置弹性beantalk以使用新版本的python

如何将所有模块移动到新版本的 Python(从 3.6 到 3.7)

Django快速安装