[Django]-How to get the difference of two querysets in Django?

35👍

Since Django 1.11, QuerySets have a difference() method amongst other new methods:

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

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

22👍

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

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

11👍

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.

0👍

In case anyone’s searching for a way to do symmetric difference, such operator is not available in Django.

That said, it’s not that hard to implement it using difference and union, and it’ll all be done in a single query:

q1.difference(q2).union(q2.difference(q1))

Leave a comment