Django过滤列之间的日期差异
Posted
技术标签:
【中文标题】Django过滤列之间的日期差异【英文标题】:Django filter on date difference between columns 【发布时间】:2018-11-09 01:31:56 【问题描述】:作为 Django 初学者,我遇到了一个非常基本的问题:根据两列的日期差异过滤表。我可以用原始 SQL 解决这个问题,但我真的很想使用基本的 Django 函数。
我有以下型号:
from django.db import models
import datetime
class Race(models.Model):
__tablename__ = 'race'
name = models.CharField(max_length=200)
country = models.CharField(max_length=100, null=True)
start = models.DateField()
end = models.DateField()
我想提取持续的比赛,例如超过 5 天。我可以通过某种方式获得一个 timediff 列:
Race.objects.annotate(tdiff=F('end')-F('start')).first()
set1 = Race.objects.annotate(tdiff=F('end')-F('start')).all()
set1.first().tdiff
现在,我如何过滤此列,我尝试的是:
min_diff = datetime.timedelta(5)
set1.filter(tdiff__gte=5).first()
set1.all().filter(tdiff__gte=min_diff)
set1.filter(tdiff__gte=min_diff).first()
但这一切都给出了:
TypeError:预期的字符串或类似字节的对象
然后我考虑使用 extra 来获取 where 子句:
set2 = Race.objects.annotate(tdiff=F('end')-F('start'))
set2.first().tdiff
set2.all().extra(where=['tdiff>=5'])
导致:
ProgrammingError:列“tdiff”不存在
同一方向的问题包括this one 和this one,但没有一个真正给出过滤新列(此处为 tdiff)的解决方案。
当最终确定这个问题时,我最终确实得到了我想要的结果:
Race.objects.filter(end__gte=F("start")+5)
print(Race.objects.filter(end__gte=F("start")+5).query)
但我还是很想知道如何利用这个临时列 tdiff。
谢谢!
回答后更新
接受的答案正是我想要的:
from django.db.models import DurationField, F, ExpressionWrapper
import datetime
set4 = Race.objects.annotate(
diff=ExpressionWrapper(F('end') - F('start'), output_field=DurationField())).filter(
diff__gte=datetime.timedelta(5))
len(set4)
# 364
len(Race.objects.filter(end__gte=F("start")+5))
# 364
【问题讨论】:
应用你的F()
函数后tdiff
的output_field
类型是什么?我的猜测是,由于您的 start
和 end
字段是 DateTime,因此您必须使用 ExpressionWrapper
将 tdiff
的 output_field
指定为 DurationField
。然后,您应该能够针对 python 的 timedelta
类型在字段上运行过滤器。 Race.objects.annotate(tdiff=ExpressionWrapper(F('end')-F('start'), output_field=DurationField()))
【参考方案1】:
这会很神奇:
from django.db.models import DurationField, F, ExpressionWrapper
import datetime
Race.objects.annotate(
diff=ExpressionWrapper(F('end') - F('start'), output_field=DurationField())
).filter(diff__gte=datetime.timedelta(5))
这将返回所有持续时间大于或等于5
的Race
实例
参考资料:
ExpressionWrapper
所以发帖-How should I use DurationField in my model?-
【讨论】:
谢谢;这行得通!我将用结果更新问题,并表明它给出的结果与我的基本解决方案相同。以上是关于Django过滤列之间的日期差异的主要内容,如果未能解决你的问题,请参考以下文章