Django 始终为真Q对象
我想创建Django ORM过滤器查询的一部分,现在我可以做:Django 始终为真Q对象,django,django-orm,django-q,Django,Django Orm,Django Q,我想创建Django ORM过滤器查询的一部分,现在我可以做: if some: Obj.filter( some_f1=some_v1, f1=v1, f2=v2, f3=v3, f4=v4, ... ) else: Obj.filter( f1=v1, f2=v2, f3=v3, f4=v4, ... ) 我想要一
if some:
Obj.filter(
some_f1=some_v1,
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
else:
Obj.filter(
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
我想要一些没有代码重复的东西,比如:
Obj.filter(
Q(some_f1=some_v1) if some else True, # what to use instead of True?
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
试试这个
conditions = {'f1':f1,'f2':f2, 'f3':f3}
if some:
conditions['some_f1'] = some_v1
Obj.objects.filter(**conditions)
根据答案,我们可以使条件参数传递
Obj.filter(
*( (Q(some_f1=some_v1),) if some else ()),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
因此,如果
some
为True
我们将tuple(Q(some\u f1=some\u v1),
添加到参数列表中,在其他情况下,我们将添加空tuple()
,我们还需要将其包装在*()
,就像我们传递非关键字参数的tuple时一样,正如Alasdair在评论中回答的那样:
Obj.filter(
Q(some_f1=some_v1) if some else Q(),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
因为,您可以创建默认过滤器,然后根据您的条件添加其他过滤器。Django在计算QuerySet之前不会运行查询(例如,在for循环中迭代查询)
以下是一种获得始终为真Q对象的黑客方法:
always_true = ~Q(pk=None)
这取决于主键不能为null这一事实。在使用AND时,“始终为真”的Q对象等同于没有Q对象(基本过滤器语法;即x和true==x
),因此您的用例的替代方案如下所示:
filters = dict(f1=v1,
f2=v2,
f3=v3,
f4=v4,
...)
if some:
filters['some_f1'] = some_v1
qs = obj.filter(**filters)
根据您的需要进行修改 如果您对这个技巧背后的逻辑添加一些注释,那就太好了(:我个人认为,将if-else逻辑移出
filter()
会更容易阅读。但是如果您喜欢这种样式,您可以使用Q()
而不带参数:Q(some\u f1=some\u v1)if-else Q()
。这避免了*args
解包的需要。Alasdair,你的评论就是答案,请发布一个总是虚假的Q对象的方法吗?它不起作用。我创建了一个问题,询问如何创建总是虚假的Q对象请注意Q()
并不是一个总是真的Q对象,它是一个空的Q对象。例如,Foobar.objects.filter(Q())
和Foobar.objects.exclude(Q())
返回所有对象。Q()
是一个坏主意。除了@Flimm提到的以外,Q()
还从例如Foobar.objects.filter(Q())中得到了优化| CONDITION)
而我们实际上只剩下Foobar.objects.filter(CONDITION)
。如果你想要一个始终为真的Q()
,那么Jonathan建议的~Q(pk\uu in=[])
似乎是最好的解决方案。但是在问题的代码中,OP确实想要Q()
需要优化,因此我不同意@DartDega的观点,认为这是一个坏主意。请注意,在相关字段上使用时,这可能会产生细微不同的结果(与将所有筛选器放在一个筛选器调用中的结果相比)。请参阅以获取替代方法。~Q(pk\u in=[])
由优化器更好地处理,并且不依赖于pk
非空值。
filters = dict(f1=v1,
f2=v2,
f3=v3,
f4=v4,
...)
if some:
filters['some_f1'] = some_v1
qs = obj.filter(**filters)