将字段添加到 DRF 通用列表视图

Add a field to DRF generic list view

我需要创建一个 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__'