Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 始终为真Q对象_Django_Django Orm_Django Q - Fatal编程技术网

Django 始终为真Q对象

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, ... ) 我想要一

我想创建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,
       ...
   )
我想要一些没有代码重复的东西,比如:

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)