Как динамически указать имя поля поиска в запросе Django?
Я хочу найти определенную строку в нескольких полях модели в Django. В идеальном случае это будет похоже на:
keyword = 'keyword'
fields = ['foo', 'bar', 'baz']
results = []
for field in fields:
lookup = "%s__contains"
results.append(Item.objects.filter(lookup=keyword))
Конечно, это не сработает, поскольку "поиск" не может быть разрешен в поле. Есть ли другой способ сделать это?
Ответы
Ответ 1
Я думаю, что может быть лучший способ сделать это с помощью системы запросов Django. Вот как это сделать по-своему.
Python позволяет передавать словари, которые будут использоваться в качестве списков аргументов, путем префикса их **.
С удачей вам нужно будет сделать что-то вроде этого:
lookup = "%s__contains" % field
results.append(Item.objects.filter(**{ lookup: keyword}))
Ответ 2
Я бы предпочел использовать объект Q для чего-то вроде этого.
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)
Ответ 3
Мне нравится DialZ-ответ, но по соображениям производительности вы должны собрать запрос, а затем сразу же ударить базу данных, а не объединить все результаты в список:
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)
Я долго не делал этого, но я уверен, что django вообще не попадет в базу данных в этом коде. Он будет выполнять только запрос при доступе к данным, содержащимся в записях