• en
  • Language: ru
  • Documentation version: 2.0

5. Как выполнить объединение двух наборов запросов из одной или разных моделей?

Оператор UNION используется для объединения наборов результатов двух или более наборов запросов. Наборы запросов могут быть из одной и той же или из разных моделей. Если наборы запросов из разных моделей, поля и их типы данных должны совпадать.

Давайте продолжим нашу модель auth_user и создадим 2 кверисета для выполнения операции объединения

>>> q1 = User.objects.filter(id__gte=5)
>>> q1
<QuerySet [<User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>
>>> q2 = User.objects.filter(id__lte=9)
>>> q2
<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>]>
>>> q1.union(q2)
<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>
>>> q2.union(q1)
<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>

Теперь попробуйте это

>>> q3 = EventVillain.objects.all()
>>> q3
<QuerySet [<EventVillain: EventVillain object (1)>]>
>>> q1.union(q3)
django.db.utils.OperationalError: SELECTs to the left and right of UNION do not have the same number of result columns

Операция объединения может быть выполнена только с наборами запросов, имеющими одинаковые поля и типы данных. Поэтому при последней операции объединения возникла ошибка. Вы можете выполнить объединение двух моделей, если они имеют одинаковые поля или одинаковые подмножества полей.

Поскольку Hero и Villain оба имеют name и gender, мы можем использовать values_list для ограничения выбранных полей, а затем выполнить объединение.

Hero.objects.all().values_list(
    "name", "gender"
).union(
Villain.objects.all().values_list(
    "name", "gender"
))

Это даст вам все объекты Hero и << 1 >>> с их именем и полом.