Home > Enterprise >  How to check if a relation exists? M2M
How to check if a relation exists? M2M

Time:04-11

I have models:

class User(models.Model):
    ...
    group = models.ManyToManyField(
        Group, related_name="users_group",
    )

class Group(models.Model):
    ....

How to check in serializer is the Group empty (there is no relationship with User)

My version is :

class GroupSerializer(serializers.ModelSerializer):
    
    empty = serializers.SerializerMethodField()
    class Meta:
        ...
        
    def get_empty(self, obj):
        return not User.objects.filter(group=obj).exists()

But maybe there is an even better way.

CodePudding user response:

If you define a ManyToManyModel [Django-doc], Django automatically defines one in reverse with the value for the related_name=… parameter [Django-doc] as name, so you can use:

class GroupSerializer(serializers.ModelSerializer):
    empty = serializers.SerializerMethodField()
    
    class Meta:
        # …
        
    def get_empty(self, obj):
        return not group.users_group.exists()

But this is not very efficient if you want to serialize a large number of Groups: for each Group it will make an extra query. You can use a BooleanField:

class GroupSerializer(serializers.ModelSerializer):
    empty = serializers.BooleanField()
    
    class Meta:
        # …

and then in the APIView or the ViewSet use as QuerySet a QuerySet where you make an annotation with an Exists subquery [Django-doc] to check if there exists a user for that Group:

from django.db.models import Exists, OuterRef
from rest_framework import viewsets

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = Group.objects.annotate(
        empty=~Exists(
            User.objects.filter(group=OuterRef('pk'))
        )
    )
    # …
  • Related