在Django中使用注释的日期时间差异

时间:2018-08-20 15:31:41

标签: django django-models django-database-functions

我有一个模型,

class Event(models.Model):
    name = models.CharField(max_length=100)
    start = models.DateTimeField()
    end = models.DateTimeField()

    @property
    def diff_days(self):
        return (self.end - self.start).days

如何在数据库级别使用diff_days获得.annotate()结果?

3 个答案:

答案 0 :(得分:2)

不幸的是,你不能。您只能注释数据库字段。这篇文章可能会对您Django annotate model custom method

有帮助

答案 1 :(得分:2)

由于使用的是 MYSQL 5.6 ,因此可以使用MYSQL的TIMESTAMPDIFF(...)函数。

我的建议是,通过将 django.db.models.expressions.Func 类继承为

来创建自定义函数(可能不适用于其他数据库)
class Format(dict):
    def __missing__(self, key):
        return '%(' + key + ')s'


class TIMESTAMPDIFF(Func):
    def __init__(self, start, end, unit='days'):
        extra = {}
        expressions = [start, end]
        extra['output_field'] = IntegerField()
        self.template = self.template % Format({"unit": unit})
        super().__init__(*expressions, **extra)

    function = 'TIMESTAMPDIFF'
    template = "%(function)s(%(unit)s, %(expressions)s)"



因此,注释查询将为

event_queryset = Event.objects.annotate(days=TIMESTAMPDIFF(F('start'), F('end'), unit='DAY' ))
参考How to implement TIMESTAMPDIFF() of MYSQL in Django

答案 2 :(得分:1)

或者您可以只使用Django内置的Extract函数来提取diff_days。然后您的查询集将类似于-

from django.db.models.functions import ExtractDay
event_queryset = Event.objects.annotate(diff_days=ExtractDay(F('end')-F('start')))