Django фильтр по списку значений столбцов

Я использую Django 3.2 и Postgres 13.

У меня есть простая модель:

from django.db import models


class Member(models.Model):

    user = models.ForeignKey("User", on_delete=models.CASCADE)
    group = models.ForeignKey("Group", on_delete=models.CASCADE)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["user", "group"], name="unique_user_group_tuple"
            )
        ]

Важной информацией здесь является UniqueConstraint, которая также создает уникальный индекс.

Допустим, у меня есть список из (user_id, group_id) кортежей:

member_tuples = [(1, 1), (2, 1), (2, 4)]

Я хотел бы получить все существующие Member объекты, соответствующие этим кортежам, при этом используя индекс. В PG я бы написал:

SELECT * from members where (user_id, group_id) in ((1, 1), (2, 1), (2, 4));

Мой вопрос: как получить нечто подобное в Django? Очевидно, что моя главная задача состоит в том, чтобы постоянно обращаться к индексу unique_user_group_tuple, чтобы избежать последовательного сканирования

На данный момент лучшим решением, которое я нашел, является следующее:

filters = Q()
for user_id, group_id in member_tuples:
    filters |= Q(user_id=user_id, group_id=group_id)

existing_members = Member.objects.filter(filters)

что переводится как

SELECT * from members WHERE (issue_id = 1 AND group_id = 1) OR (issue_id = 2 AND group_id = 1) OR (issue_id = 2 AND group_id = 4); 

Это также запрашивает индекс, но не создает ожидаемый запрос.

Итак, я пытаюсь достичь двух разных вещей:

  • найти способ аннотировать запись, например, вернуть что-то вроде: SELECT (user_id, group_id) as member_tuple FROM member
  • использовать коллекцию записей в предложении WHERE: WHERE something IN ((1,1), (2,1) (2,4));
Вернуться на верх