我想创建一些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,
...
)
答案 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,
...
)
因此,如果some
为True
,我们将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
根据您的需要进行修改。