2013-09-04 6 views
0

Я использую Django 1.4.3 w/Python 2.7 на Ubuntu 13.04. Я столкнулся с проблемой и не могу найти решение.Фильтр Django __contains = queryset?

У меня есть серия связанных моделей (через FK), и мне нужно их фильтровать сложным способом.

Предположим, у меня есть модель Car, которая имеет Parts. Я могу получить все части как car.parts_set. Каждая часть имеет поле M2M excluded_price до Price, с related_name='excluded_prices'.

Если я создаю новую деталь, мне нужно добавить цены на номер excluded_price, где каждая цена имеет excluded_parts для каждой другой части, относящейся к этому автомобилю. Я пытаюсь создать фильтр, чтобы помочь мне найти эти цены.

По существу я хочу что-то вроде этого:

parts_set = [part for part in car.parts_set.exclude(pk=new_part.pk)] 
Price.objects.filter(excluded_parts__contains=parts_set) 

Эффективно я хочу, чтобы найти все цены, где excluded_parts супер набор отдельных частей автомобиля (за исключением новой части, очевидно).

Я нашел отличный способ сделать это, если «parts_set» был серией строк.

parts_set = [Q(excluded_parts__contains=part) for part in car.parts_set.exclude(pk=new_part.pk)] 
Price.objects.filter(reduce(operator.and_, parts_set)) 

К сожалению __contains работает только для строк с SQL заявлением LIKE.

Есть ли какие-либо функции в ORM Django, поддерживающие фильтр типа __contains, который обрабатывает значение как объект, а не строку?

+0

Вы имеете в виду оператора '__in'? – mariodev

+0

Нет, 'excluded_parts' является супер-множеством, поэтому я бы ожидал, что' parts_set' будет '__in'' excluded_parts', а не наоборот. – Rico

ответ

1

Если я следую ваш вопрос правильно, вы можете сделать это путем итеративного построения ограничений на QuerySet:

parts_set = car.parts_set.exclude(pk=new_part.pk) 
price_qs = Price.objects.all() 
for part in parts_set: 
    price_qs = price_qs.filter(excluded_parts=part) 

Это потребует, что цены в конечном QuerySet есть все части из результата parts_set в их excluded_parts раздел. У них могут быть и другие части. price_qs должны в конечном итоге возвращаются желаемые результаты:

все цены, где excluded_parts супер набор отдельных частей автомобиля

Я не знаю лучшего способа построить запрос, требующий, чтобы поле many-to-many должно содержать несколько конкретных значений.

+0

Ничего себе, это полностью работает, и я не понимаю, почему они выбрали этот синтаксис. «Excluded_parts = part» дует мне в голову. Это M2M ... равенство не имеет смысла! Спасибо хоть. :) – Rico

+0

Равенство на M2M означает, что «это значение должно быть в M2M». Это довольно хорошо для некоторых распространенных случаев, таких как «Является ли текущий пользователь в данной группе безопасности?». По-видимому, это по крайней мере частично по аналогии с FK. Когда вы объединяете фильтры, все они должны быть истинными, поэтому заканчивается: «все price_q должны быть в M2M». –

Смежные вопросы