DjangoRest框架-如何获得序列化器中相关字段的计数和平均值

ogsagwnx  于 2023-02-06  发布在  Go
关注(0)|答案(1)|浏览(129)

我有一个帖子模型,可以有评级:
下面是帖子模型:

class Post(models.Model):

    category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT, default=1, related_name="posts")
    body = models.TextField("content", blank=True, null=True, max_length=5000)
    slug = AutoSlugField(populate_from=["category", "created_at"])
    video = models.FileField(upload_to=video_directory_path, null=True, blank=True)
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="posts"
    )
    published = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "post"
        verbose_name_plural = "posts"
        db_table = "posts"
        ordering = ["created_at"]
        get_latest_by = "created_at"

    def __str__(self):
        return self.body[0:30]

    def get_absolute_url(self):
        return self.slug

    def one_image(self):
        return PostImage.objects.all().filter(post=self)[:1]

这是一个事后评价模型:

class PostRating(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="ratings")
    score = models.IntegerField(choices=list(zip(range(1, 6), range(1, 6))))
    user = models.ForeignKey(
        User, on_delete=models.CASCADE, verbose_name="user rating"
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")

    class Meta:
        verbose_name = "post rating"
        verbose_name_plural = "post ratings"
        db_table = "post_ratings"

    def __str__(self):
        return str(self.score)

下面是序列化器:

class PostSerializer(serializers.ModelSerializer):
    images = PostImageSerializer(many=True, read_only=True, required=False)
    
    class Meta:
        model = Post
        fields = [
            "id",
            "category",
            "body",
            "images",
            "video",
            "ratings",
            "published",
            "created_at",
            "updated_at",
        ]
        depth = 1

    def create(self, validated_data):
        user = User.objects.get(id=self.context['request'].data.get('user'))
        category = Category.objects.get(id=self.context['request'].data.get('category'))
        new_post = Post.objects.create(**validated_data, category=category, user=user)
        images = dict((self.context['request'].FILES).lists()).get('images', None)
        if images:
            for image in images:
                PostImage.objects.create(
                    image=image, post=new_post
                )
        return new_post
    • 问题:**

在序列化器中,我有一个相关的字段"ratings",它显示了一个数组,其中包含了每个评级,这很好,但我只想得到评级的总数和平均值。我如何才能在序列化器中获得这些信息,以便在前端显示为评级总数和评级平均值?

uttx8gqw

uttx8gqw1#

如果我理解你的问题你可以这样做。

class PostSerializer(serializers.ModelSerializer):
    images = PostImageSerializer(many=True, read_only=True, required=False)
    total_ratings = serializers.SerializerMethodField()
    average_rating = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = [
            "id",
            "category",
            "body",
            "images",
            "video",
            "ratings",
            "total_ratings",
            "average_rating",
            "published",
            "created_at",
            "updated_at",
        ]
        depth = 1

    def get_total_ratings(self, obj):
        return obj.ratings.count()

    def get_average_rating(self, obj):
        total = obj.ratings.aggregate(Sum('score'))['score__sum']
        if total:
            return total / obj.ratings.count()
        return 0

    #rest of your logic and code

相关问题