2009-08-04 2 views
16

Ich möchte nach einer bestimmten Zeichenfolge in mehreren Feldern eines Modells in Django suchen. Idealerweise wäre es etwas ähnliches gehen:Wie dynamisch Lookup-Feldname in Django Abfrage?

keyword = 'keyword' 
fields = ['foo', 'bar', 'baz'] 
results = [] 
for field in fields: 
    lookup = "%s__contains" 
    results.append(Item.objects.filter(lookup=keyword)) 

Natürlich ist dies nicht funktionieren wird, als „Nachschlag“ kann nicht in ein Feld gelöst werden. Gibt es einen anderen Weg, dies zu tun?

+0

Danke für den dupe link - ich suchte danach, aber es ist schwer, die richtige Kombination von Keywords in diesem zu treffen. –

Antwort

15

Ich denke, es gibt möglicherweise eine bessere Möglichkeit, dies mit dem Django-Abfrage-System zu tun. Hier ist, wie Sie es auf Ihre Art und Weise tun können.

In Python können Sie Wörterbücher, die als Argumentliste verwendet werden sollen, übergeben, indem Sie ihnen ** vorangestellt werden. Mit einem Spot Glück, sollten Sie in der Lage sein, so etwas zu tun, aber aus Leistungsgründen

lookup = "%s__contains" % field 
results.append(Item.objects.filter(**{ lookup: keyword})) 
+0

Werfen Sie einen Blick auf Botondus Antwort unten. Es ist die Lösung mit dem Django-Abfragesystem, auf das ich mich bezog, und es sollte hoffentlich schneller laufen, da es in SQL ausgeführt wird. –

4

I DialZ Antwort mögen, sollten Sie die Abfrage erstellen und dann die Datenbank einmal statt verketten alle Ergebnisse in eine Liste:

keyword = 'keyword' 
fields = ['foo', 'bar', 'baz'] 

# this makes an empty queryset object which we can 
# add to later using the | operator 
results = Item.objects.none() 

for field in fields: 
    lookup = "%s__contains" % field 
    query = {lookup : keyword} 
    results = results | Item.objects.filter(**query) 

I havn't eine davon in eine Weile getan, aber ich bin mir ziemlich sicher, dass django wird nicht wirklich die Datenbank überhaupt in diesem Code getroffen. Es wird nur eine Abfrage ausführen, wenn Sie auf die in den Datensätzen enthaltenen Daten zugreifen.

23

Ich würde lieber das Q-Objekt für so etwas verwenden.

from django.db.models import Q 

keyword = 'keyword' 
fields = ['foo', 'bar', 'baz'] 

Qr = None 
for field in fields: 
    q = Q(**{"%s__contains" % field: keyword }) 
    if Qr: 
     Qr = Qr | q # or & for filtering 
    else: 
     Qr = q 

# this you can now combine with other filters, exclude etc.  
results = MyModel.objects.filter(Qr) 
+1

Das ist eine absolut wundervolle Antwort. Es hat mir den Tag verschlagen. Hast du irgendwo darüber geschrieben? Ich glaube nicht, dass die meisten Leute erkennen, dass dies möglich ist (Schleifen von Feldnamen, um ein Diktat von Q-Objekt-Kwargs zu füllen). – jMyles

+1

@jMyles: Danke, froh, dass ich helfen konnte. Nein, ich glaube nicht, dass ich anderswo darüber geschrieben habe. Aber im Allgemeinen "Q" Objekte auf dynamische Weise zu kombinieren, ist eine sehr leistungsfähige Methode, um komplexe Abfragen einfach zu erstellen. –

+0

Ich habe gerade eine Frage gestellt, auf die die Antwort ähnlich sein könnte - ich kann eine Schleife und den AN-Operator von Q verwenden. Es ist hier: http://stackoverflow.com/questions/6783747/django-queryset-to-match-all-related-objects – jMyles