如何解决在django上使用F和timedelta进行查询
|| 我有以下模型:class Process(models.Model):
title = models.Charfield(max_length=255)
date_up = models.DateTimeField(auto_now_add=True)
days_activation = models.PositiveSmallIntegerField(default=0)
现在,我需要根据它们的值days_activation
查询所有已过期的Process
对象。
我试过了
from datetime import datetime,timedelta
Process.objects.filter(date_up__lte=datetime.now()-timedelta(days=F(\'days_activation\')))
并收到以下错误消息:
TypeError:timedelta days组件的不受支持的类型:F
我当然可以用Python做到:
filter (lambda x: x.date_up<=datetime.now() - timedelta(days=x.days_activation),Process.objects.all ()),
但是我真的需要出5英镑。
解决方法
您必须扩展聚合。像下面这样:
from django.db import models as DM
class BaseSQL(object):
function = \'DATE_SUB\'
template = \'%(function)s(NOW(),interval %(expressions)s day)\'
class DurationAgr(BaseSQL,DM.Aggregate):
def __init__(self,expression,**extra):
super(DurationAgr,self).__init__(
expression,output_field=DM.DateTimeField(),**extra
)
Process.objects.filter(date_up__lte=DurationAgr(\'days_activation\'))
希望它将为您工作。 :)
, 您正在混合两层:运行时层和数据库层。 F
函数只是一个帮助程序,可让您使用django ORM构建稍微复杂的查询。您一起使用ѭ8和ѭ7,并期望django ORM足够聪明,可以将这些内容转换为原始SQL,但是据我所知,它做不到。也许我错了,对django ORM一无所知。
无论如何,您可以额外重写您的ORM调用,并使用等于datetime.now()
和timedelta
的本机SQL函数手动构建WHERE子句。
, 7天== 1天* 7
F
是深黑色的Django魔法,以及遇到它的物体
必须属于适当的魔法界来处理。
在您的情况下,django.db.models.query.filter
知道F
,但datetime.timedelta
不知道。
因此,您需要将F
排除在timedelta
参数列表之外。
幸运的是,F
支持timedelta * int
的乘法,
所以以下可以工作:
Process.objects.filter(date_up__lte=datetime.now()-timedelta(days=1)*F(\'days_activation\'))
事实证明,这将适用于PostgreSQL,但不适用于SQlite(对于Django 1.11,仅timedelta
支持+
和-
,
可能是由于相应的SQlite限制)。
, 我尝试使用上面Lutz Prechelt的解决方案,但遇到了MySQL语法错误。
这是因为我们无法在MySQL中使用INTERVAL执行算术运算。
因此,对于MySQL,我的解决方案是创建一个自定义DB函数:
class MysqlSubDate(Func):
function = \'SUBDATE\'
output_field = DateField()
用法示例:
.annotate(remainded_days=MysqlSubDate(\'end_datetime\',F(\'days_activation\')))
您也可以使用timedelta,它将转换为INTERVAL
.annotate(remainded_days=MysqlSubDate(\'end_datetime\',datetime.timedelta(days=10)))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。