Django ORM计算两个日期属性之间的天数

时间:2015-02-20 10:05:23

标签: python django django-orm

方案

我有一张桌子student。它有以下属性

name

age

school_passout_date

college_start_date

我需要一份报告,以了解avg number of days学生在通过学校和开始上大学之间获得免费的机会。

目前的方法

目前,我正在为每个学生寻找天数并获得平均值而烦恼。

问题

当记录集变大时,效率非常低。

问题

Django ORM中是否有任何能力可以在两个日期之间给出总天数?

可能性

我正在寻找这样的东西。

Students.objects.filter(school_passed=True, started_college=True).annotate(total_days_between=Count('school_passout_date', 'college_start_date'), Avg_days=Avg('school_passout_date', 'college_start_date'))

最佳,

4 个答案:

答案 0 :(得分:2)

数学上,根据(预期)事实,传递日期总是晚于开始日期,你可以平均取消所有开始日期和所有传递日期,并产生差异。< / p>

这为您提供了类似的解决方案

from django.db.models import Avg
avg_start_date = Students.objects.filter(school_passed=True, started_college=True).aggregate(Avg('school_start_date'))
avg_passout_date = Students.objects.filter(school_passed=True, started_college=True).aggregate(Avg('school_passout_date'))
avg_time_at_college = avg_passout_date - avg_start_date

答案 1 :(得分:1)

Django目前只接受4个函数的聚合:Max,Min,Count和et Average,所以这有点棘手。

然后解决方案使用方法extra。那样:

Students.objects.
    extra(select={'difference': 'school_passout_date' - 'college_start_date'}).
    filter('school_passed=True, started_college=True)

但是,你仍然必须在服务器端做平均值

答案 2 :(得分:1)

这个问题已经很久了,但现在Django ORM更先进了。

可以使用F()函数执行此操作。

from django.db.models import Avg, F
college_students = Students.objects.filter(school_passed=True, started_college=True)
duration = college_students.annotate(avg_no_of_days=Avg( F('college_start_date') - F('school_passout_date') )

答案 3 :(得分:0)

您可以这样做:

Model.objects.annotate(age=Cast(ExtractDay(TruncDate(Now()) - TruncDate(F('created'))), IntegerField()))

这使您可以使用整数值,例如,您可以执行以下操作:

from django.db.models import IntegerField, F
from django.db.models.functions import Cast, ExtractDay, TruncDate

qs = (
    Model
    .objects
    .annotate(age=Cast(ExtractDay(TruncDate(Now()) - TruncDate(F('created'))), IntegerField()))
    .annotate(age_bucket=Case(
        When(age__lt=30, then=Value('new')),
        When(age__lt=60, then=Value('current')),
        default=Value('aged'),
        output_field=CharField(),
    ))
)