How to get the difference of two querysets in Djan

2019-02-05 20:47发布

问题:

I have to querysets. alllists and subscriptionlists

alllists = List.objects.filter(datamode = 'A')
subscriptionlists = Membership.objects.filter(member__id=memberid, datamode='A')

I need a queryset called unsubscriptionlist, which possess all records in alllists except the records in subscription lists. How to achieve this?

回答1:

You should be able to use the set operation difference to help:

set(alllists).difference(set(subscriptionlists))


回答2:

Since Django 1.11, QuerySets have a difference() method amongst other new methods. (Source: https://docs.djangoproject.com/en/1.11/releases/1.11/#models)

qs_diff = qs_all.difference(qs_part)    # Capture elements that are in qs_all but not in qs_part

Also see: https://stackoverflow.com/a/45651267/5497962



回答3:

Well I see two options here.

1. Filter things manually (quite ugly)

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. Just make another query

diff = List.objects.filter(datamode = 'A').exclude(member__id=memberid, datamode='A')


回答4:

How about:

subscriptionlists = Membership.objects.filter(member__id=memberid, datamode='A')
unsubscriptionlists = Membership.objects.exclude(member__id=memberid, datamode='A')

The unsubscriptionlists should be the inverse of subscription lists.

Brian's answer will work as well, though set() will most likely evaluate the query and will take a performance hit in evaluating both sets into memory. This method will keep the lazy initialization until you need the data.