Django: Как использовать строку в качестве ключевого слова в выражении Q ()? - PullRequest
7 голосов
/ 16 ноября 2011

Я пишу простую форму поиска для определенной модели. Давайте назовем модель Orchard и присвоим ей атрибуты apples, oranges и pears только для демонстрации.

Итак, форма не требует заполнения всех полей. Таким образом, вы можете искать на apples и oranges, но не груши. Мне их нужно отфильтровать так:

Orchard.objects.filter(apples=request.GET.get('apples'), oranges=request.GET.get('oranges'), pears=request.GET.get('pears'))

но если pears пусто, результаты никогда не вернутся.

Моей первой мыслью было использование Q объектов, что-то вроде этого:

from django.db.models import Q

options = {}
options['apples'] = request.GET.get('apples')
options['oranges'] = request.GET.get('oranges')
options['pears'] = request.GET.get('pears')

queries = None

for key in options:
    if options[key] != u'':
        if queries:
            queries &= Q(key=options[key]) # <=== problem here
        else:
            queries = Q(key=options[key])  # <=== same problem here

results = Orchard.objects.filter(queries)

Проблема возникает в этих отмеченных линиях. Я, очевидно, не могу просто использовать «ключ» в качестве ключевого слова атрибута, потому что он не принимает строку, он по существу принимает переменную.

Итак ... как мне обойти это?

Если нет известного решения этой проблемы, не включающего Q. Это тоже было бы полезно.

Ответы [ 2 ]

12 голосов
/ 16 ноября 2011

это общая проблема с использованием переменной в качестве ключа в ключевом слове arg. решение состоит в том, чтобы обернуть вещи в диктовку и распаковать это:

queries &= Q(**{key: options[key]})

или в вашем случае

for option in options:
    if options[option] is None:
        del(options[option])
# or otherwise only add the ones you actually want to filter on
# then
results = Orchard.objects.filter(**options)
0 голосов
/ 16 ноября 2011

@ секундный ответ правильный, распакуйте словарь с оператором ** для предоставления аргументов ключевых слов.

Однако, если вы используете только AND для объединения Q объектов ине ИЛИ , тогда вам на самом деле не нужно использовать Q объекты в вашем примере.Просто создайте словарь поиска, а затем используйте его в качестве аргумента для ключевого слова для filter.

options = {}
for key in ('apples', 'oranges', 'pears'):
    value = request.GET.get(key)
    if value:
        options[key] = value
results = Orchard.objects.filter(**options)
...