Come fornire dinamicamente il nome del campo di ricerca nella query Django? [duplicare]
-
22-07-2019 - |
Domanda
Questa domanda ha già una risposta qui:
Voglio cercare una certa stringa in diversi campi di una Model in Django. Idealmente, andrebbe qualcosa di simile a:
keyword = 'keyword'
fields = ['foo', 'bar', 'baz']
results = []
for field in fields:
lookup = "%s__contains"
results.append(Item.objects.filter(lookup=keyword))
Ovviamente questo non funzionerà, come " cerca " non può essere risolto in un campo. C'è un altro modo per farlo?
Soluzione
Penso che potrebbe esserci un modo migliore per farlo con il sistema di query Django. Ecco come farlo a modo tuo.
Python ti consente di passare dizionari da utilizzare come elenchi di argomenti con il prefisso **. Con un po 'di fortuna, dovresti essere in grado di fare qualcosa del genere:
lookup = "%s__contains" % field
results.append(Item.objects.filter(**{ lookup: keyword}))
Altri suggerimenti
Preferirei usare l'oggetto Q per qualcosa del genere.
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)
Mi piace la risposta di DialZ ma per motivi di prestazioni dovresti creare la query e poi colpire una volta il database invece di concatenare tutti i risultati in un elenco:
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)
Non ne ho fatto uno da un po 'di tempo, ma sono abbastanza sicuro che django in realtà non colpirà affatto il database in questo codice. Eseguirà una query solo quando accedi ai dati contenuti nei record