我是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输出
如果有人在最后一点(即约会)也能帮助我,我将不胜感激。
答案 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