Как получить разницу двух наборов запросов в Django?
Я должен запросить наборы. все списки и подписки
alllists = List.objects.filter(datamode = 'A')
subscriptionlists = Membership.objects.filter(member__id=memberid, datamode='A')
Мне нужен набор запросов, называемый unsubscriptionlist, который обладает всеми записями во всех списках, кроме записей в списках подписки. Как этого добиться?
5 ответов
Начиная с Django 1.11, QuerySets имеет difference()
метод среди других новых методов. (Источник: https://docs.djangoproject.com/en/1.11/releases/1.11/)
qs_diff = qs_all.difference(qs_part) # Capture elements that are in qs_all but not in qs_part
Вы должны быть в состоянии использовать установленную разницу операций, чтобы помочь:
set(alllists).difference(set(subscriptionlists))
Ну, я вижу два варианта здесь.
1. Фильтровать вещи вручную (довольно некрасиво)
diff = []
for all in alllists:
found = False
for sub in subscriptionlists:
if sub.id == all.id:
found = True
break
if not found:
diff.append(all)
2. Просто сделайте еще один запрос
diff = List.objects.filter(datamode = 'A').exclude(member__id=memberid, datamode='A')
Как насчет:
subscriptionlists = Membership.objects.filter(member__id=memberid, datamode='A')
unsubscriptionlists = Membership.objects.exclude(member__id=memberid, datamode='A')
Списки отписки должны быть обратными спискам подписки.
Ответ Брайана также будет работать, хотя set(), скорее всего, оценит запрос и снизит производительность при оценке обоих наборов в памяти. Этот метод будет сохранять ленивую инициализацию до тех пор, пока вам не понадобятся данные.
Если кто-то ищет способ сделать симметричную разницу, такой оператор недоступен в Django.
Тем не менее, это не так сложно реализовать, используяdifference
иunion
, и все это будет сделано в одном запросе:
q1.difference(q2).union(q2.difference(q1))