Home > other >  Serialize filtered related fields in Django Rest framework
Serialize filtered related fields in Django Rest framework

Time:06-17

In my project, I have three models: Group, User and Challenge. Each user is a member of some groups and each challenge is intended for one or more groups.

class Group(TimeStampedModel):
    name = models.CharField(max_length=255)

class User(AbstractUser):
    user_groups = models.ManyToManyField(Group)

class Challenge(TimeStampedModel):
    ...
    groups = models.ManyToManyField(Group, null=True, blank=True)

I also have a serializer for Challenge models that serializes all challenge data and related groups using a GroupSerializer.

class ChallengeSerializer(serializers.ModelSerializer):

    groups = GroupSerializer(many=True)

    class Meta:
        model = Challenge
        fields = [..., "groups"]

My current APIView for serializing list of challenges.

class ChallengeList(generics.ListAPIView):
    queryset = Challenge.objects.all()
    serializer_class = ChallengeSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_queryset(self):
        user_groups = self.request.user.user_groups.all()
        return Challenge.objects.filter(groups__in=user_groups).distinct()

When serializing a Challenge object, a list of all related groups is serialized.

Is it possible to only serialize related Group objects that are also related to our currently logged in user?

CodePudding user response:

you could use a SerializerMethodField() to filter down the Challenges groups to just the user groups. To do this you may also need to pass in serializer context as well

To set up the serializer context:

class ChallengeList(generics.ListAPIView):
...
def get_serializer_context(self):
   context = {user_groups: self.request.user.user_groups.all()}
   return context
...

Then access this context in the SerializerMethodField in your serializer

class ChallengeSerializer(serializers.ModelSerializer):

    groups_of_user = SerializerMethodField()

    class Meta:
        model = Challenge
        fields = [..., "groups_of_user"]

    def get_groups_of_user(self, challenge):
        user_groups = self.context.get('user_groups')
        groups_of_user = challenge.groups & user_groups
        return GroupSerializer(groups_of_user, many=True).data

With this implementation you could also add prefetch_related('groups') on your queryset in ChallengeList to improve performance

  • Related