Сериализация отфильтрованных связанных полей во фреймворке Django Rest

В моем проекте есть три модели: Group, User и Challenge. Каждый пользователь является членом некоторых групп, и каждая задача предназначена для одной или нескольких групп.

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)

У меня также есть сериализатор для Challenge моделей, который сериализует все данные вызова и связанные группы с помощью GroupSerializer.

class ChallengeSerializer(serializers.ModelSerializer):

    groups = GroupSerializer(many=True)

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

Мой текущий APIView для сериализации списка вызовов.

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

При сериализации объекта Challenge сериализуется список всех связанных групп.

Возможно ли сериализовать только связанные Group объекты, которые также связаны с нашим текущим вошедшим пользователем?

вы можете использовать SerializerMethodField() для фильтрации групп Challenges только до групп пользователей. Для этого вам также может понадобиться передать контекст сериализатора

Для настройки контекста сериализатора:

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

Затем обратитесь к этому контексту в SerializerMethodField в вашем сериализаторе

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

При такой реализации вы также можете добавить prefetch_related('groups') на ваши queryset в ChallengeList для улучшения производительности

Вернуться на верх