如何使用预取子查询功能注释Django查询集

时间:2020-05-17 19:12:57

标签: python django-models django-rest-framework

我想在查询集上有一个字段status,该字段是根据一组预取的反馈值的函数得出的。

反馈示例:

feedback = [
    {'action': 0, 'user': 1},
    {'action': 1, 'user': 13},
]

如果我是在Serializer上编写的,我会这样做:

    def get_status(self, obj):
        # Squash all feedback into single status value
        fb = obj.feedback.all()
        vals = [f.action for f in fb]
        if len(vals) == 0:
            return 0  # Unconfirmed
        if sum(vals) == 0:
            return 1 # Confirmed
        return 2  # Rejected

不过,我想将此逻辑下移到视图的查询集中以启用对该字段的排序。

queryset = Foo.objects\
        .prefetch_related('feedback')\
        .annotate(status="???")

我想知道哪些可用的查询表达式集可以模仿上面的python函数get_status的逻辑。

1 个答案:

答案 0 :(得分:2)

由于数据库层不了解函数,因此无法在.annotate(..)中调用函数。您可以尝试将以上内容转换为表达式。您不需要为此需要.prefetch_related(..)。在这里您可以使用Case [Django-doc]When [Django-doc]

from django.db.models import Case, Count, IntegerField, Sum, Value, When

queryset = Foo.objects.annotate(
    nfeedback=Count('feedback'),
    sumfeedback=Sum('feedback__action')
).annotate(
    status=Case(
       When(nfeedback=0, then=Value(0)),
       When(sumfeedback=0, then=Value(1)),
       default=Value(2),
       output_field=IntegerField()
    )
)