Always True Q 对象
Always True Q object
我想动态创建 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)
根据this答案我们可以使条件参数传递
Obj.filter(
*( (Q(some_f1=some_v1),) if some else ()),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
所以,如果 some
是 True
我们将元组 (Q(some_f1=some_v1),)
添加到参数列表,在其他情况下我们添加空元组 ()
,我们还需要将它包装起来在 *()
中,当我们传递非关键字参数
的元组时,一如既往
正如 Alasdair 在评论中的回答:
Obj.filter(
Q(some_f1=some_v1) if some else Q(),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
自 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)
这里有一个获取始终为真的 Q 对象的 hacky 方法:
always_true = ~Q(pk=None)
这取决于主键不能为空。
"always true" Q 对象在使用 AND(基本过滤器语法;即 x and True == x
)时等同于 No Q 对象,因此您的用例的 DRYer 替代方案如下:
filters = dict(f1=v1,
f2=v2,
f3=v3,
f4=v4,
...)
if some:
filters['some_f1'] = some_v1
qs = obj.filter(**filters)
根据您的需要进行修改。
我想动态创建 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)
根据this答案我们可以使条件参数传递
Obj.filter(
*( (Q(some_f1=some_v1),) if some else ()),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
所以,如果 some
是 True
我们将元组 (Q(some_f1=some_v1),)
添加到参数列表,在其他情况下我们添加空元组 ()
,我们还需要将它包装起来在 *()
中,当我们传递非关键字参数
正如 Alasdair 在评论中的回答:
Obj.filter(
Q(some_f1=some_v1) if some else Q(),
f1=v1,
f2=v2,
f3=v3,
f4=v4,
...
)
自 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)
这里有一个获取始终为真的 Q 对象的 hacky 方法:
always_true = ~Q(pk=None)
这取决于主键不能为空。
"always true" Q 对象在使用 AND(基本过滤器语法;即 x and True == x
)时等同于 No Q 对象,因此您的用例的 DRYer 替代方案如下:
filters = dict(f1=v1,
f2=v2,
f3=v3,
f4=v4,
...)
if some:
filters['some_f1'] = some_v1
qs = obj.filter(**filters)
根据您的需要进行修改。