Django Rest Framework - 注释重复值
Django Rest Framework - Annotate duplicates values
我遇到了一个非常奇怪的错误。在注释 3 个值(AVG、COUNT 和 SUM)时,我注意到 COUNT 和 SUM 相互相乘。
例如:
持续时间应该是一半,并且只有 2 个评分(number_of_ratings - COUNT,album_duration - SUM)。
我在 ViewSet 的查询集中有这些注释 class
class AlbumViewSet(ModelViewSet):
queryset = Album.objects \
.prefetch_related("tracks", "album_genres", "album_genres__genre_id", "album_links", "reviews") \
.select_related("aoty", "artist_id") \
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField()),
album_duration=Sum("tracks__duration", output_field=DurationField()))
这是其他文件
models.py
class Album(models.Model):
RELEASE_TYPE_ALBUM_CHOICES = [
("LP", "LP"),
("EP", "EP"),
("Single", "Single"),
("Live", "Live"),
]
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
release_date = models.DateField()
artist_id = models.ForeignKey(
Artist, on_delete=models.PROTECT, related_name="albums"
)
art_cover = ResizedImageField(
size=[750, 750], null=True, blank=True, upload_to=rename_album_art_cover)
release_type = models.CharField(max_length=10,
choices=RELEASE_TYPE_ALBUM_CHOICES, default="LP")
created_at = models.DateTimeField(auto_now_add=True)
class Track(models.Model):
title = models.CharField(max_length=255)
position = models.PositiveIntegerField()
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="tracks")
duration = models.DurationField(null=True)
class Review(models.Model):
reviewer_id = models.ForeignKey(Reviewer, on_delete=models.PROTECT)
rating = models.IntegerField(
validators=[MaxValueValidator(100), MinValueValidator(0)]
)
review_text = models.TextField(null=True, blank=True)
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="reviews")
created_at = models.DateTimeField(auto_now_add=True)
serializer.py
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
genres = StringRelatedField(
source="album_genres", many=True)
aoty = StringRelatedField(read_only=True)
links = AlbumLinkSerializer(
source="album_links", many=True, read_only=True)
artist = SimpleArtistSerializer(source="artist_id", read_only=True)
overall_score = serializers.IntegerField(read_only=True)
number_of_ratings = serializers.IntegerField(read_only=True)
album_duration = serializers.DurationField(read_only=True)
class Meta:
model = Album
fields = [
"id",
"title",
"slug",
"created_at",
"artist",
"art_cover",
"genres",
"overall_score",
"number_of_ratings",
"release_date",
"release_type",
"tracks",
"album_duration",
"links",
"aoty"
]
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ["position", "title", "duration", "album_id"]
class ReviewSerializer(serializers.ModelSerializer):
reviewer = SimpleReviewerSerializer(source="reviewer_id", read_only=True)
album = ReviewAlbumSerializer(source="album_id", read_only=True)
class Meta:
model = Review
fields = [
"id",
"reviewer_id",
"reviewer",
"rating",
"review_text",
"album_id",
"album",
"created_at"
]
对于遇到相同问题的任何人,以下是我的解决方法。
每个注释函数中都应该设置不同的属性。
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField(), distinct=True),
album_duration=Sum("tracks__duration", output_field=DurationField(), distinct=True))
我遇到了一个非常奇怪的错误。在注释 3 个值(AVG、COUNT 和 SUM)时,我注意到 COUNT 和 SUM 相互相乘。
例如:
持续时间应该是一半,并且只有 2 个评分(number_of_ratings - COUNT,album_duration - SUM)。
我在 ViewSet 的查询集中有这些注释 class
class AlbumViewSet(ModelViewSet):
queryset = Album.objects \
.prefetch_related("tracks", "album_genres", "album_genres__genre_id", "album_links", "reviews") \
.select_related("aoty", "artist_id") \
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField()),
album_duration=Sum("tracks__duration", output_field=DurationField()))
这是其他文件
models.py
class Album(models.Model):
RELEASE_TYPE_ALBUM_CHOICES = [
("LP", "LP"),
("EP", "EP"),
("Single", "Single"),
("Live", "Live"),
]
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
release_date = models.DateField()
artist_id = models.ForeignKey(
Artist, on_delete=models.PROTECT, related_name="albums"
)
art_cover = ResizedImageField(
size=[750, 750], null=True, blank=True, upload_to=rename_album_art_cover)
release_type = models.CharField(max_length=10,
choices=RELEASE_TYPE_ALBUM_CHOICES, default="LP")
created_at = models.DateTimeField(auto_now_add=True)
class Track(models.Model):
title = models.CharField(max_length=255)
position = models.PositiveIntegerField()
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="tracks")
duration = models.DurationField(null=True)
class Review(models.Model):
reviewer_id = models.ForeignKey(Reviewer, on_delete=models.PROTECT)
rating = models.IntegerField(
validators=[MaxValueValidator(100), MinValueValidator(0)]
)
review_text = models.TextField(null=True, blank=True)
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="reviews")
created_at = models.DateTimeField(auto_now_add=True)
serializer.py
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
genres = StringRelatedField(
source="album_genres", many=True)
aoty = StringRelatedField(read_only=True)
links = AlbumLinkSerializer(
source="album_links", many=True, read_only=True)
artist = SimpleArtistSerializer(source="artist_id", read_only=True)
overall_score = serializers.IntegerField(read_only=True)
number_of_ratings = serializers.IntegerField(read_only=True)
album_duration = serializers.DurationField(read_only=True)
class Meta:
model = Album
fields = [
"id",
"title",
"slug",
"created_at",
"artist",
"art_cover",
"genres",
"overall_score",
"number_of_ratings",
"release_date",
"release_type",
"tracks",
"album_duration",
"links",
"aoty"
]
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ["position", "title", "duration", "album_id"]
class ReviewSerializer(serializers.ModelSerializer):
reviewer = SimpleReviewerSerializer(source="reviewer_id", read_only=True)
album = ReviewAlbumSerializer(source="album_id", read_only=True)
class Meta:
model = Review
fields = [
"id",
"reviewer_id",
"reviewer",
"rating",
"review_text",
"album_id",
"album",
"created_at"
]
对于遇到相同问题的任何人,以下是我的解决方法。 每个注释函数中都应该设置不同的属性。
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField(), distinct=True),
album_duration=Sum("tracks__duration", output_field=DurationField(), distinct=True))