2016-09-28 91 views
2

我在阅读this article动态生成Q对象。我的理解(大部分)问对象,但我不明白作者是如何具体是这样做的例子:了解Django Q - 动态

# string representation of our queries 
>>> predicates = [('question__contains', 'dinner'), ('question__contains', 'meal')] 

# create the list of Q objects and run the queries as above.. 
>>> q_list = [Q(x) for x in predicates] 

>>> Poll.objects.filter(reduce(operator.or_, q_list)) 
[<Poll: what shall I make for dinner>, <Poll: what is your favourite meal?>] 

我特别不明白的是列表理解。 A Q对象使用任意关键字参数进行格式化,如Q(question__contains='dinner')

如果像作者建议的那样使用列表理解,那么不会在每次迭代中将一个元组放入一个Q对象中吗?像这样:Q(('question__contains', 'dinner'))

我不确定此代码如何生成格式正确的Q对象。

回答

4

该文章依赖于Q()接受args以及kwargs的未记录功能。

如果您看source code for the Q class,您会发现它在__init__方法中执行以下操作。

class Q(tree.Node): 
    ... 
    def __init__(self, *args, **kwargs): 
     super(Q, self).__init__(children=list(args) + list(kwargs.items())) 

如果你在一个空的元组()kwargs调用Q(question__contains=dinner)然后args是一本字典{'question__contains': 'dinner'}。在super()调用,children变量是

children = list(args) + list(kwargs.items()) 

计算结果为

children = list(()) + list(('question__contains', 'dinner'),) 

其简化为

children = [('question__contains', 'dinner')] 

请注意,您还可以,如果你使用Q(('question__contains', 'dinner'))得到这样的结果。在这种情况下,args是元组(('question__contains', 'dinner'),)kwargs是空字典{}

super()通话时,children变量计算

children = list((('question__contains', 'dinner'),)) + list([]) 

它像以前一样简化了相同的结果,

children = [('question__contains', 'dinner')] 

我们已经证明Q(question__contains=dinner)相当于Q(('question__contains', 'dinner')),因此你可以通过在列表理解中遍历2元组的列表来生成Q()对象的列表。

>>> predicates = [('question__contains', 'dinner'), ('question__contains', 'meal')] 
>>> q_list = [Q(x) for x in predicates] 

就个人而言,我可能更喜欢写

>>> predicates = [{'question__contains': 'dinner'}, {'question__contains': 'meal'}] 
>>> q_list = [Q(**kwargs) for kwargs in predicates] 

这样,你是不是依靠Q__init__方法的行为。

+0

绝对真棒。非常感谢您的介绍。 – qarthandso