Найти - Пользователи
Полная версия: filter с динамическим количеством параметров, каждый из которых Q
Начало » Django » filter с динамическим количеством параметров, каждый из которых Q
1
m3ou
Следующая проблема
Пользователь вводит различные критерии поиска. Если он их вводит - то ищем по этим критериям(принимают участие в select -filter посредством Q)
Если не вводит - то по ним не ищем.
Запрос вида select * from table_name where col1=val1 and col2=val2 and ….. and coln in ()… and ….
Как сие правильно перевести на джанговский ORM?

Пока что делаю тупым путём.
            if q_1:
location_str = "Q(location__in=[%s])," % ",".join([str(cur.id) for cur in q_1])
if sform.cleaned_data['has_photo']:
photo_str = "~Q(ph1='') | ~Q(ph2='') | ~Q(ph3='') | ~Q(ph4=''),"
if sform.cleaned_data['description']:
descr_str = "Q(description__contains=sform.cleaned_data['description']),"
if sform.cleaned_data['publisher']:
publisher_str = "Q(user_id=sform.cleaned_data['publisher'].id),"
......................
Далее делаю так

exec("""q_object = Object.objects.filter(
%(location_str)s
%(photo_str)s
%(descr_str)s
%(publisher_str)s
.................
)""" % { 'location_str': location_str, 'descr_str': descr_str, 'publisher_str': publisher_str, 'photo_str': photo_str, ...}
)
Но что-то мне подсказывает, что можно обойтись без exec-а.
Может нехватает знания языка… Думал сделать с помощью распаковки аргументов ** или * , да вот в качестве каждого аргумента идёт Q или ~Q….

Кто-то просто-тки должен был столкнуться с такой проблемой.
Буду очень благодарен за помощь. Или хотя бы за намёк, в какую сторону копать.
Александр Кошелев
m3ou
Думал сделать с помощью распаковки аргументов ** или * , да вот в качестве каждого аргумента идёт Q или ~Q….
Правильно думали, так и делайте. Это правильный путь. И конечно никаких exec.
Ferroman
Daevaorn
Эээ, ты понял что он хотел?


ЗЫ: Я об код чуть глаза не сломал. Почему у переменных такие странные названия?
Александр Кошелев
Ferroman
Эээ, ты понял что он хотел?
Зменить кодогенерацию на обычные языковые конструкции:-)

Тут нужно заредьюсить все условия в один объект Q и его передать в filter.
m3ou
Зменить кодогенерацию на обычные языковые конструкции:-)
Именно. Так красиво сказать не получилось - опыта маловато :)
Тут нужно заредьюсить все условия в один объект Q и его передать в filter.
А чуток поконкретнее? Как заредьюсить? Разве не для того был написан Q, чтобы он использовался в одном фильтре несколько раз, только применялся
к разным полям…

О том, что как-то можно, я догадывался, поэтому и спрашивал…
Александр Кошелев
m3ou
Разве не для того был написан Q, чтобы он использовался в одном фильтре несколько раз, только применялся
к разным полям…
Объект Q это обертка над оператором сравнения. Но обертка не простая - она может содержать в себе “дерево” из других таких же объектов. В общем, если захотите, то можете код Джанги на досуге почитать.

А ваш пример следует переписать например так:
q = Q()
if q_1:
q &= Q(location__in=q_1)
if sform.cleaned_data['has_photo']:
q &= ~Q(ph1='') | ~Q(ph2='') | ~Q(ph3='') | ~Q(ph4='')
if sform.cleaned_data['description']:
q &= Q(description__contains=sform.cleaned_data['description'])
if sform.cleaned_data['publisher']:
q &= Q(user=sform.cleaned_data['publisher'])

objects = Object.objects.filter(q)
Ferroman
attributes =
Object.objects.filter(reduce(or_, , value=item) for item in attributes]))
m3ou
Спасибо огромное, теперь картина прояснилась
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB