如何在django中获得布尔结果?

时间:2020-07-20 15:16:53

标签: django django-rest-framework django-queryset

我有一个过滤器,该过滤器应返回带有2个对象的查询集,并且应具有一个不同的字段。例如:

obj_1 = (name='John', age='23', is_fielder=True)
obj_2 = (name='John', age='23', is_fielder=False)

这两个对象的模型相同,但是主键不同。我尝试使用以下过滤器:

qs = Model.objects.filter(name='John', age='23').annotate(is_fielder=F('plays__outdoor_game_role')=='Fielder')

我第一次使用注释,但这给了我以下错误:

TypeError: QuerySet.annotate() received non-expression(s): False.

我是Django的新手,所以我在做错什么,获取上面所示的必需对象的注释应该是什么?

2 个答案:

答案 0 :(得分:0)

您可以将Case/Whenannotate一起使用

from django.db.models import Case, BooleanField, Value, When
Model.objects.filter(name='John', age='23').annotate(
    is_fielder=Case(
        When(plays__outdoor_game_role='Fielder', then=Value(True)),
        default=Value(False),
        output_field=BooleanField(),
    ),
)

答案 1 :(得分:0)

@ktowen 的解决方案运行良好,非常简单。 这是我正在使用的另一个解决方案,希望它也有帮助。

queryset = queryset.annotate(is_fielder=ExpressionWrapper(
            Q(plays__outdoor_game_role='Fielder'),
            output_field=BooleanField(),
        ),)

这里给不熟悉 Django ORM 的人一些解释:

注释 动态创建一个新列/字段,在本例中为 is_fielder。这意味着您的模型中没有名为 is_fielder 的字段,而您可以在添加此“注释”后像 plays.outdor_game_role.is_fielder 一样使用它。 Annotate 非常有用且灵活,几乎可以与其他所有表达式结合使用,应该是 Django ORM 中的必备方法。

ExpressionWrapper 基本上为您提供了空间来包装更复杂的条件组合,以类似 ExpressionWrapper(expression, output_field) 的格式使用。当您组合不同类型的字段或想要指定输出类型时,它很有用,因为 Django 无法自动判断。

Q object 是一个常用的指定条件的表达式,我认为最强大的部分是可以链接条件:

  1. AND (&):filter(Q(condition1) & Q(condition2))
  2. 或 (|):filter(Q(condition1) | Q(condition2))
  3. 否定(~):filter(~Q(condition))

可以在如下正常条件下使用 Q: (Q(condition1)|id__in=[list])

重点是Q对象必须排在第一位,否则将无法工作。

Case When(then) 可以简单地解释为 if con1 elif con2 elif con3 ...。它非常强大,而且我个人喜欢用它来自定义查询集的排序对象。

例如,您需要返回一个观看历史条目的查询集,这些条目必须按照用户观看的顺序排列。您可以使用 for 循环来保持顺序,但这会生成大量类似的查询。 Case When 的一种更优雅的方式是:

item_ids = [list]
ordering = Case(*[When(pk=pk, then=pos)
           for pos, pk in enumerate(item_ids)])
watch_history = Item.objects.filter(id__in=item_ids)\
                .order_by(ordering)

如您所见,通过使用 Case When(then) 可以绑定那些非常具体的关系,可以将其视为 1) 精确/精确的条件表达式和 2) 在连续多个条件的情况下特别有用。