Django:如何在Q()语句中使用字符串作为关键字?
我正在为一个特定的模型写一个简单的搜索表单。我们把这个模型叫做 Orchard
,它有一些属性,比如 apples
(苹果)、oranges
(橙子)和 pears
(梨子),这样方便演示。
这个表单不要求所有字段都必须填写。也就是说,你可以只搜索 apples
和 oranges
,而不填 pears
。我需要这样来过滤数据:
Orchard.objects.filter(apples=request.GET.get('apples'), oranges=request.GET.get('oranges'), pears=request.GET.get('pears'))
但是如果 pears
这个字段是空的,就永远不会有结果返回。
我最初的想法是使用 Q
对象,类似这样:
from django.db.models import Q
options = {}
options['apples'] = request.GET.get('apples')
options['oranges'] = request.GET.get('oranges')
options['pears'] = request.GET.get('pears')
queries = None
for key in options:
if options[key] != u'':
if queries:
queries &= Q(key=options[key]) # <=== problem here
else:
queries = Q(key=options[key]) # <=== same problem here
results = Orchard.objects.filter(queries)
问题出现在那些标记的行上。我显然不能直接用“key”作为属性的关键词,因为它不接受字符串,而是需要一个变量。
那么……我该怎么解决这个问题呢?
除非有其他已知的解决方案,不涉及 Q
的方法,那样也会很有帮助。
2 个回答
4
@second的回答是对的,可以用**
这个操作符来解包字典,从而提供关键字参数。
不过,如果你只是用AND来组合Q
对象,而不是OR,那么在你的例子中其实不需要使用Q
对象。你只需要构建一个包含查找条件的字典,然后把这个字典作为filter
的关键字参数使用就可以了。
options = {}
for key in ('apples', 'oranges', 'pears'):
value = request.GET.get(key)
if value:
options[key] = value
results = Orchard.objects.filter(**options)
28
这是一个常见的问题,当你在使用变量作为关键字参数的键时。解决这个问题的方法是把内容放在一个字典里,然后再展开它:
queries &= Q(**{key: options[key]})
或者在你的情况下
for option in options:
if options[option] is None:
del(options[option])
# or otherwise only add the ones you actually want to filter on
# then
results = Orchard.objects.filter(**options)