没有过滤的Django条件注释

时间:2017-06-11 20:07:23

标签: python mysql django annotations conditional

我有学生模型和入门模型。每个条目都有一个学生的外键,一个年票和两个数值(value1和value2)。我正在覆盖StudentAdmin类中的get_queryset()方法,并且使用Django ORM,我想要注释一个我们将调用的字段" specialvalue"。

学生每年最多只有一个参赛作品,但他们可能没有参赛作品,未来可能会有参赛作品。 "特殊值"的值对于当前年份的Entry,将等于Entry__value1减去Entry__value2。如果学生当年没有参赛作品,那么特殊价值将等于无,并且不会从查询集中删除这些学生。

我该怎么做?起初我尝试将查询集拆分为两个:

queryset_1 = queryset.filter(entry__year=THIS_YEAR).annotate(specialvalue=...)
queryset_2 = queryset.exclude(entry__year=THIS_YEAR).annotate(specialvalue=Value(None))

然后单独注释它们并将它们与|合并管道运算符,但不幸的是,由于known bug in Django's ORM导致错误的结果。

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为,使用Django条件表达式将适用于您的情况。有关更多信息,请阅读Case表达式(https://docs.djangoproject.com/en/1.11/ref/models/conditional-expressions/#case)。您只需检查条目是否与CURRENT_YEAR相关。

  

Case()接受任意数量的When()对象作为单独的参数。使用关键字参数提供其他选项。如果没有条件评估为TRUE,则返回使用default keyword参数给出的表达式。如果未提供默认参数,则使用None。

我没有测试过这个解决方案,但我认为它应该可行:

from django.db.models import Case, When, F, IntegerField
queryset = queryset.annotate(
    specialvalue=Case(
        When(entry__year=THIS_YEAR, 
             then=F('entry__value1') - F('entry__value2')
        ), output_field=IntegerField()
    )
).values_list('specialvalue')