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

时间:2019-05-17 16:48:24

标签: python django serialization django-rest-framework

我是Django Rest Framework中的新手,并且进行了练习。我想从两个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网址应该:

  • 应该根据指定日期范围内添加到电影中的评论数量(如示例)返回数据库排名中已经存在的热门电影。响应中应包含电影的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输出

如果有人在最​​后一点(即约会)也能帮助我,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

我认为您可以这样做:

# 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个额外的字段。它将从查询集中捕获带注释的值,并显示为输出。

答案 1 :(得分:0)

我认为您应该在自己的视图中重写get方法:

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