Добавить поле в представление общего списка 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__'