如何从两个序列化器中创建自定义输出JSON



我是Django的REST框架中的新手,我有一个练习。我想从两种Django型号创建自定义JSON输出。我已经创建了两个序列化视图。输出JSON应该是:

{
    "movie_id": 2,
    "total_comments": 4,
    "rank": 1
},
{
    "movie_id": 3,
    "total_comments": 2,
    "rank": 2
},
{
    "movie_id": 4,
    "total_comments": 2,
    "rank": 2
}

,get/top URL应该:

  • 应根据在指定日期范围内添加到电影中添加的许多注释(如示例(中返回数据库排名中已经存在的顶级电影。响应应包括电影的ID,等级的位置和评论总数(在指定的日期范围内(。

  • 具有相同数量评论的电影在排名中应具有相同的位置。

  • 应要求指定应生成统计信息的日期范围。

我有两个序列化:

class CommentSerializer(serializers.ModelSerializer):
   class Meta:
      model= Comment
      fields=('movie','user','timestamp','content','approved')
class MovieSerializer(DynamicFieldsModelSerializer,serializers.HyperlinkedModelSerializer):
     comments=CommentSerializer(many=True)
     comments=None
    class Meta:
        model = Movie
        fields = ('id','name','description','year','released','comments','rating')

这是评论模型:

class Comment(models.Model):
     movie = models.ForeignKey(Movie, on_delete=models.DO_NOTHING,related_name='comments',blank=True,null=True)
    content = models.TextField()
    timestamp = models.DateTimeField(default=timezone.now)
    user=models.CharField(max_length=250)

我试图通过这个技巧自己做到这一点:

class MovieViewSet(viewsets.ModelViewSet):
      queryset = Movie.objects.all()
      serializer_class = MovieSerializer
class CommentViewSet(viewsets.ModelViewSet):
      queryset = Comment.objects.all()
      serializer_class = CommentSerializer
class TopViewSet(viewsets.ModelViewSet):
      serializer_class = MovieSerializer
      #queryset = Movie.objects.annotate(comment_count=(Count('comments'))).order_by("-comment_count","-rating")
       queryset = Movie.objects.all().annotate(comment_count=(Count('comments'))).order_by("-comment_count")

,但我不知道如何创建自定义的JSON输出

如果有人在最后一点也可以帮助我,即日期,我会很感激。

我想你可以这样做:

# serializer
class MovieSerializer(HyperlinkedModelSerializer):
     comments = CommentSerializer(many=True)
     comments_count = serializer.IntegerField()
     rank = serializer.IntegerField()
    class Meta:
        model = Movie
        fields = ('id','name','description','year','released','comments','rating', 'comments_count', 'rank')
# Viewset
from django.db.models import Sum, F
from django.db.models.expressions import Window
from django.db.models.functions import Rank

class TopViewSet(viewsets.ModelViewSet):
      serializer_class = MovieSerializer
      queryset = Movie.objects.all()
       def get_queryset(self, *args, **kwargs):
          from_date = self.request.query_params.get('from_date')
          to_date = self.request.query_params.get('to_date')
          movies = super(ToViewSet, self).get_queryset()
          if from_date and to_date:
               movies = movies.filter(release__range=[from_date, to_date])
          return movies.annotate(comment_count=Count('comments'), rank=Window(expression=Rank(), order_by=F('comments').desc()),)

说明:

get_queryset()方法中,我使用 self.request.query_params.get(...) 。这用于获取 URL Querystring 。因此,当您调用/your_url/?from_date=2018-01-01&to_date=2019-01-31时,它将在给定的日期范围之间过滤queryset。

另外,我已经使用了django模型的 Window Function 来注释对象的等级。

最后,在序列化器中,我在Serializer中添加了2个额外的字段。它将从QuerySet捕获带注释的值并显示为输出。

我认为您应该在视图中重写获取方法:

from rest_framework.response import Response
from rest_framework import status


class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    def get(self):
        """ do some thing"""
        output = {{    
                    "movie_id": 2,
                    "total_comments": 4,
                    "rank": 1
                   },
                   {
                    "movie_id": 3,
                    "total_comments": 2,
                    "rank": 2
                   },
                   {
                    "movie_id": 4,
                    "total_comments": 2,
                    "rank": 2
                    }
                   }
        return Response(output, status=status.HTTP_200_OK)

有关更多详细信息,请阅读DRF文档:https://www.django-rest-framework.org/api-guide/generic-views/#generic-views

最新更新