2016-09-28 20 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