始终是真Q对象

时间:2015-11-04 08:55:57

标签: 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,
       ...
   )

我想要一些没有代码重复的东西:

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,
    ...
)

6 个答案:

答案 0 :(得分:8)

这是获得永远真实的Q对象的一种愚蠢方式:

always_true = ~Q(pk=None)

这取决于主键不能为空的事实。

答案 1 :(得分:3)

试试这个;

conditions = {'f1':f1,'f2':f2, 'f3':f3}
if some:
    conditions['some_f1'] = some_v1

Obj.objects.filter(**conditions)

答案 2 :(得分:2)

正如阿拉斯戴尔在评论中所说:

Obj.filter(
    Q(some_f1=some_v1) if some else Q(), 
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)

答案 3 :(得分:1)

基于this回答,我们可以使条件参数传递

Obj.filter(
    *( (Q(some_f1=some_v1),) if some  else ()),    
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)

因此,如果someTrue,我们将tuple (Q(some_f1=some_v1),)添加到参数列表中,在其他情况下我们添加空元组(),我们还需要将其包装在{ {1}},就像我们传递非关键字args的元组一样

答案 4 :(得分:0)

QuerySets are lazy开始,您可以创建默认过滤器,然后根据您的条件添加其他过滤器。 Django不会运行查询,直到评估QuerySet(例如,在for循环中迭代它)

filtered_objects = Obj.filter(
    some_f1=some_v1,
    f1=v1,
    f2=v2,
    f3=v3,
    f4=v4,
    ...
)
if some:
    filtered_objects.filter(some_f1=some_v1)

答案 5 :(得分:0)

使用AND(基本过滤器语法;即const outcome = obj.map(o => ({ ...o, sites: o.sites .map(s => ({ ...s, roleName: o.roles .find(r => r.id === s.roleId).name, })), })); )时,“始终为真”的Q对象等效于No Q对象,因此您的用例的DRYer替代方法如下:

x and True == x

根据您的需要进行修改。