Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django find exact match for Many To Many relationship

Tags:

sql

psql

django

Lets say tat I have such a model:

class Conversation(models.Model):
    sid = models.CharField(
        max_length=34,
        primary_key=True
    )
    members = models.ManyToManyField(to=User)

I would like to find a Conversation that is connected exactly/only with users [1,2]

I tried this:

conversation = Conversation.objects.filter(
            members__in=[1, 2]
        )

But it returns all conversation that are connected with either user 1, or 2.

I tried this: other answer but It returns empty queryset.

like image 738
Przemek Avatar asked Oct 20 '25 01:10

Przemek


1 Answers

We can count how many members match the list, and check if that includes all the members:

from django.db.models import Count, Q

members = [1,2]
members_len = len(set(members))

Conversation.objects.annotate(
    total_members=Count('members'),
    matching_members=Count('members', filter=Q(members__in=members))
).filter(
    matching_members=members_len,
    total_members=members_len
)

This thus will retrieve Converstions that contain all members in the members list, and only these members (so not a superset, nor a subset).

Or for pre django-2.0 installations:

from django.db.models import Case, Count, When

members = [1,2]
members_len = len(set(members))

Conversation.objects.annotate(
    total_members=Count('members'),
    matching_members=Count(Case(
        When(members__in=members, then='members'),
        default=None
    ))
).filter(
    matching_members=members_len,
    total_members=members_len
)
like image 71
Willem Van Onsem Avatar answered Oct 22 '25 16:10

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!