我有一个过滤器,它应该返回一个查询集与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')
我第一次使用annotate,但它给了我下面的错误:
TypeError: QuerySet.annotate() received non-expression(s): False.
我是Django的新手,那么我做错了什么,应该做什么注解才能得到如上所示的所需对象?
2条答案
按热度按时间b1uwtaje1#
@ktowen的解决方案很好用,相当简单。这里是我正在使用的另一个解决方案,希望它也有帮助。
这里有一些解释给那些不熟悉Django ORM的人:
Annotate动态创建一个新的列/字段,在本例中为
is_fielder
。这意味着您的模型中没有名为is_fielder
的字段,而在添加此“annotation”后,您可以像使用plays.outdor_game_role.is_fielder
一样使用它。Annotate
非常有用和灵活,几乎可以与任何其他表达式组合,应该是Django ORM中的一个MUST-KNOWN方法。ExpressionWrapper基本上给了你空间来 Package 更复杂的条件组合,以
ExpressionWrapper(expression, output_field)
这样的格式使用。当你组合不同类型的字段或想要指定输出类型时,它很有用,因为Django不能自动判断。Q object是一个经常用来指定条件的表达式,我认为最强大的部分是它可以链接条件:
1.与(&):
filter(Q(condition1) & Q(condition2))
1.或(|):
filter(Q(condition1) | Q(condition2))
1.阴性(~):
filter(~Q(condition))
可以在如下正常条件下使用Q:
(Q(condition1)|id__in=[list])
关键是Q对象必须先到达,否则它将不起作用。
**Case When(then)**可以简单地解释为
if con1 elif con2 elif con3 ...
,它相当强大,就我个人而言,我喜欢用它来为一个查询集定制一个排序对象。例如,你需要返回一个观看历史条目的查询集,这些条目必须按照用户观看的顺序排列。你可以使用for循环来保持顺序,但这会生成大量类似的查询。使用Case When的一个更优雅的方法是:
正如您所看到的,通过使用
Case When(then)
,可以绑定那些非常具体的关系,可以将其视为1)精确的条件表达式,2)在连续多个条件的情况下特别有用。3xiyfsfu2#
可以将
Case/When
与annotate
一起使用