2016-09-28 1 views
2

Ich lese this article auf dynamische Generierung von Q-Objekten. Ich verstehe (zum größten Teil) Q-Objekte, aber ich bin nicht zu verstehen, wie der Autor speziell dieses Beispiel macht:Verstehen von Django Q - Dynamisch

# 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?>] 

Was ich speziell nicht bekommen, ist die Liste Verständnis. Ein Q Objekt wird mit willkürlichen Schlüsselwörtern als solche Q(question__contains='dinner') formatiert.

Wenn es so tut, wie der Autor mit dem Listenverständnis vorschlägt, wird das effektiv nicht einfach ein Tupel innerhalb eines Q Objekts auf jeder Iteration platzieren? Wie zum Beispiel: Q(('question__contains', 'dinner')).

Ich bin mir nicht sicher, wie dieser Code ein korrekt formatiert Q Objekt erzeugt.

Antwort

4

Der Artikel stützt sich auf die undokumentierte Funktion, Q() akzeptiert Args sowie Kwargs.

Wenn Sie source code for the Q class betrachten, können Sie sehen, dass es die folgenden in der __init__ Methode tut.

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

Wenn Sie Q(question__contains=dinner) dann args in einem leeren Tupel nennen () und kwargs ist ein Wörterbuch {'question__contains': 'dinner'}. Im super() Aufruf ist die children Variable

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

die

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

zu

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

Hinweis

vereinfacht, dass Sie auch dieses Ergebnis bekommen könnte, wenn Sie Q(('question__contains', 'dinner')) verwenden. In diesem Fall ist args ein Tupel (('question__contains', 'dinner'),) und kwargs ist ein leeres Wörterbuch {}.

Im super() Aufruf wird die children Variable ausgewertet

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

, die nach wie vor zu dem gleichen Ergebnis vereinfacht,

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

Wir haben gezeigt, dass Q(question__contains=dinner) zu Q(('question__contains', 'dinner')) gleichwertig ist und Sie deshalb kann die Liste der Q() Objekte durch Schleifen einer Liste von 2-Tupeln in einem Listenverständnis erzeugen.

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

Ich persönlich könnte es vorziehen,

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

diese Weise zu schreiben, Sie sind auf dem Verhalten der __init__ Methode der Q nicht verlassen.

+0

Absolut genial. Vielen Dank für das Durchlaufen. – qarthandso