首页 > 解决方案 > 如何使用预取子查询的功能注释 django 查询集

问题描述

我想在查询集上有一个字段,该字段status派生自一组预取的反馈值的函数。

反馈示例:

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

如果我在序列化器上写这个,我会这样做:

    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="???")

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

标签: pythondjango-modelsdjango-rest-framework

解决方案


您不能在 an 中调用函数,.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()
    )
)

推荐阅读