Rajasekar
Rajasekar

Reputation: 18978

How to get the difference of two querysets in Django?

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?

Upvotes: 29

Views: 32812

Answers (5)

João Haas
João Haas

Reputation: 2139

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))

Upvotes: 0

markus-hinsche
markus-hinsche

Reputation: 1432

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

Upvotes: 38

Gevious
Gevious

Reputation: 3252

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.

Upvotes: 4

Brian Fisher
Brian Fisher

Reputation: 24009

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

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

Upvotes: 22

Silver Light
Silver Light

Reputation: 46002

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')

Upvotes: 11

Related Questions