Django многие ко многим: лучший способ получить элементы в одном связанном наборе запросов, но исключить элементы в других связанных наборах запросов? - PullRequest
2 голосов
/ 06 января 2020

Рассмотрим следующие связанные модели:

class A(models.Model):
    name = models.CharField(max_length=250, unique=True)
    bs = models.ManyToManyField(B)

class B(models.Model):
    pass

В представлении мне нужно выполнить запрос, чтобы получить все B s, связанные с данным A , исключая при этом все B s связано с набором других A s. Мне нужна серая область:

enter image description here

Мой нынешний, крайне неэффективный подход заключается в следующем:

bs_for_a1 = A.objects.get(name=a1).bs.all()

for previous_A in previous_As:
    previous_bs = A.objects.get(name=previous_A).bs.all()
    bs_for_a1 = bs_for_a1.difference(previous_bs)

В моем приложении, previous_As может иметь около 1000 элементов, что делает этот подход чрезвычайно дорогим. Есть лучший способ сделать это? У меня есть полный контроль над ремонтом моделей / схемы. Я хотел бы, чтобы любой заданный запрос, включая выбор связанных моделей и связанную с ним сортировку, заканчивался sh менее чем за 1 секунду.

Я думаю, что лучший подход мог бы включать необработанный запрос SQL непосредственно при переходе Таблица. Я использую Django 3.0 с sqlite. Производство будет использовать Postgres.

1 Ответ

2 голосов
/ 13 января 2020

Кажется, я делал это сложнее, чем нужно. Это похоже на работу для данной иллюстрации:

previous_As = (a2.name, a3.name, a4.name)
b1_minus_previous = B.objects.exclude(a__name__in=previous_As).filter(a__name=a1)
...