Добавить поле в представление общего списка DRF

Мне нужно создать представление списка DRF, которое показывает каждый курс вместе с булевым полем, указывающим, подписан ли пользователь, запрашивающий представление, на курс.

Подписки на курсы хранятся в следующей модели:

class Subscription(models.Model):
   user = models.ForeignKey(
      CustomUser, related_name='subscriptions', null=False, 
      on_delete=CASCADE)
   course = models.ForeignKey(
      Course, related_name='subscriptions', null=False,
      on_delete=CASCADE)

   class Meta:
      ordering = ['course', 'user']
      unique_together = [['user', 'course']]

Вот представление, которое я пишу:

class CourseListView(generics.ListAPIView):
   permission_classes = [IsAuthenticated, ]
   queryset = Course.objects.all()
   serializer_class = CourseSerializer
   
   def isSubscribed(self, request, course):
      sub = Subscription.objects.filter(
         user=request.user, course=course).first() 
      return True if sub else False

   def list(self, request, format=None):
      queryset = Course.objects.all()
      serializer = CourseSerializer(queryset, many=True)
      return Response(serializer.data)

Я ищу способ модифицировать метод list, чтобы добавить в ответ информацию о том, подписан ли request.user на каждый из курсов.

Лучшее решение, которое у меня есть на данный момент, это построить serializer вручную, что будет выглядеть (на уровне псевдокода) примерно так:

serializer = []
for course in querySet:
    course['sub'] = self.isSubscribed(request, course)
    serializer.append(CourseSerializer(course))

Я подозреваю, что должен существовать лучший (стандартный, идиоматический, менее запутанный) способ добавления пользовательского поля в представлении списка, но не смог его найти. Кроме того, мне интересно, можно ли избежать попадания в базу данных для каждого курса.

Вы можете легко сделать это с помощью Exists:

просто измените ваш набор запросов в представлении:

from django.db.models import Exists, OuterRef

class CourseListView(generics.ListAPIView):
    permission_classes = [IsAuthenticated, ]
    serializer_class = CourseSerializer

    def get_queryset(self):
        subquery = Subscription.objects.filter(user=request.user, course=OuterRef('id'))
        return Course.objects.annotate(sub=Exists(subquery))

и добавьте поле для него в вашем сериализаторе:

class CourseSerializer(serializers.ModelSerializer):
    sub = serializers.BooleanField(read_only=True)

    class Meta:
        model = Course
        fields = '__all__'
Вернуться на верх