Джанго ОРМ.Отфильтруйте много ко многим с помощью предложения AND - PullRequest
0 голосов
/ 21 мая 2018

Со следующими моделями:

class Item(models.Model):
    name = models.CharField(max_length=255)
    attributes = models.ManyToManyField(ItemAttribute)


class ItemAttribute(models.Model):
    attribute = models.CharField(max_length=255)
    string_value = models.CharField(max_length=255)
    int_value = models.IntegerField()

У меня также есть Item, который имеет 2 атрибута, 'color': 'red' и 'size': 3.

Если я сделаю любую из этихзапросы:

Item.objects.filter(attributes__string_value='red')
Item.objects.filter(attributes__int_value=3)

Я получу Item возвращено, работает, как я ожидал.

Однако, если я попытаюсь сделать несколько запросов, например:

Item.objects.filter(attributes__string_value='red', attributes__int_value=3)

Все, что я хочу сделать, это AND.Это также не будет работать:

Item.objects.filter(Q(attributes__string_value='red') & Q(attributes__int_value=3))

Вывод:

<QuerySet []>

Почему?Как я могу построить такой запрос, чтобы мой Item был возвращен, потому что он имеет атрибут red и атрибут 3?

1 Ответ

0 голосов
/ 21 мая 2018

Если это полезно, вы можете объединить выражения фильтра в Django:

query = Item.objects.filter(attributes__string_value='red').filter(attributes__int_value=3')

Из DOCS :

Это займет начальный QuerySetиз всех записей в базе данных, добавляет фильтр, затем исключение, затем другой фильтр.Конечным результатом является QuerySet, содержащий все записи с заголовком, начинающимся с «Что», которые были опубликованы в период с 30 января 2005 г. по текущий день.

Для этого нужно .filter(), нос динамическими аргументами:

args = {
    '{0}__{1}'.format('attributes', 'string_value'): 'red',
    '{0}__{1}'.format('attributes', 'int_value'): 3
}

Product.objects.filter(**args)

Вы можете также (если вам нужно сочетание AND и OR) использовать объекты Q Джанго .

Запросы аргументов ключевого слова - в фильтре () и т. Д. - объединяются «И».Если вам нужно выполнить более сложные запросы (например, запросы с операторами OR), вы можете использовать объекты Q.

AQ объект (django.db.models.Q) - это объект, используемый для инкапсуляции коллекцииключевые аргументы.Эти ключевые аргументы указаны как в «Полевых поисках» выше.

Вы бы имели что-то вроде этого вместо того, чтобы иметь все Q objects в этом фильтре:

** import Q from django
from *models import Item

#assuming your arguments are kwargs
final_q_expression = Q(kwargs[1])
for arg in kwargs[2:..]
    final_q_expression = final_q_expression & Q(arg);
result = Item.objects.filter(final_q_expression)

Thisэто код, который я не запускал, он не в моей голове.Считайте это псевдокодом, если хотите.

Хотя это не объясняет, почему способы, которые вы пробовали, не совсем работают.Возможно, это связано с поиском , который охватывает отношения , и таблицами, которые объединяются для получения этих значений.Я бы предложил напечатать yourQuerySet.query, чтобы визуализировать формирующийся raw SQL, который поможет вам понять, почему .filter( Q() & Q()) не работает.

...