返回模型中值的平均值,而不是每个值

时间:2019-12-23 16:06:20

标签: python django

我正在尝试在Django中制作一个Movie项目。我希望对电影的收视率有一个看法,该看法可以采用单个rate_value,但通过GET返回电影的收视率平均值。

我不知道我应该从哪里开始。我试图在视图和序列化程序中进行一些更改,但是没有起作用。这里是:

views.py:

class RateListView(generics.ListCreateAPIView):
    permission_classes = [AllowAny]
    serializer_class = RateSerializer
    lookup_url_kwarg = 'rateid'

    def get_queryset(self):
        rateid = self.kwargs.get(self.lookup_url_kwarg)
        queryset = Rate.objects.filter(film = rateid)
        # .aggregate(Avg('rate_value'))

        if queryset.exists():
            return queryset
        else:
            raise Http404

    def post(self, request, *args, **kwargs):
        serializer = RateSerializer(data = request.data)

        if serializer.is_valid():
            if Film.objects.filter(pk = self.kwargs.get(self.lookup_url_kwarg)).exists():
            serializer.save(film_id = self.kwargs.get(self.lookup_url_kwarg))
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            raise Http404

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializer.py

class RateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rate
        fields = ('rate_value',)

和model.py

class Rate(models.Model):
    film = models.ForeignKey(Film, on_delete = models.CASCADE)
    rate_value = models.IntegerField(validators = [
                        MinValueValidator(1),
                        MaxValueValidator(10)
                        ]
    )

    def __str__(self):
        return str(self.film.title) + str(self.rate_value)

现在,它可以正确返回单个值。

2 个答案:

答案 0 :(得分:0)

class Film(models.Model:
    ...

    @property
    def mean_rating(self):
        ratings = self.ratings.all().values_list('rate_value', flat=True)
        if ratings:
            return sum(ratings)/len(ratings)
        # return a separate default value here if no ratings

class Rate(models.Model):
    film = models.ForeignKey(Film, on_delete = models.CASCADE, related_name='ratings')
    rate_value = models.IntegerField(validators = [
                        MinValueValidator(1),
                        MaxValueValidator(10)
                        ]
    )

...

class FilmSerializer(serializers.ModelSerializer):
    class Meta:
        model = Film
        fields = ('id','name','mean_rating',)

在不进入应用程序体系结构的情况下,可以使用以下模式。电影对象具有计算属性,该属性调用ratings(提供给电影评分的related_name)以获取所有相关评分并返回均值。

只要可以提供可序列化的值,就可以将模型的属性用作序列化器字段。

有关Django中模型的related_name的更多信息,请参见此处-What is `related_name` used for in Django?

答案 1 :(得分:0)

尝试这样的事情:

serializers.py

class RateListSerializer(serializers.Serializer):
    avg_rate_value = serializers.FloatField()    


class RateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rate
        fields = ("rate_value", "film")

views.py

class RateListView(generics.ListCreateAPIView):
    permission_classes = [AllowAny]

    def get_queryset(self):
        if self.action == "list":
            queryset = Film.objects.all()
            film_id = self.request.query_params.get("film_id", None)
            if film_id is not None:
                queryset = queryset.filter(id=film_id)
            return queryset.annotate(avg_rate_value=Avg("rate__rate_value"))
        return Rate.objects.all()

    def get_seializer_class(self):
        if self.action == "list":
            return RateListSerializer
        return RateSerializer