mirror of
https://github.com/narrrl/holy-flavor-rater.git
synced 2026-11-03 16:41:27 +01:00
79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
from django.db.models import Count
|
|
from rest_framework import serializers
|
|
|
|
from api.models import Category, Flavor, Rating
|
|
from api.serializers._helpers import absolute_image_url
|
|
from api.serializers.rating import RatingSerializer
|
|
|
|
|
|
class CategorySerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Category
|
|
fields = ["id", "name", "slug"]
|
|
|
|
|
|
class FlavorSerializer(serializers.ModelSerializer):
|
|
category_name = serializers.CharField(source="category.name", read_only=True)
|
|
category_slug = serializers.CharField(source="category.slug", read_only=True)
|
|
average_rating = serializers.FloatField(read_only=True)
|
|
followed_average_rating = serializers.FloatField(read_only=True)
|
|
user_rating = serializers.SerializerMethodField()
|
|
ratings = RatingSerializer(many=True, read_only=True)
|
|
image_url = serializers.SerializerMethodField()
|
|
image_urls = serializers.SerializerMethodField()
|
|
rating_distribution = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Flavor
|
|
fields = [
|
|
"id",
|
|
"name",
|
|
"category",
|
|
"category_name",
|
|
"category_slug",
|
|
"description",
|
|
"average_rating",
|
|
"followed_average_rating",
|
|
"user_rating",
|
|
"ratings",
|
|
"image_url",
|
|
"image_urls",
|
|
"image",
|
|
"is_available",
|
|
"is_legacy",
|
|
"shop_url",
|
|
"rating_distribution",
|
|
]
|
|
extra_kwargs = {"image": {"write_only": True}}
|
|
|
|
def get_image_url(self, obj: Flavor) -> str | None:
|
|
if obj.image:
|
|
return absolute_image_url(self, obj.image)
|
|
return obj.image_url
|
|
|
|
def get_image_urls(self, obj: Flavor) -> list[str]:
|
|
urls: list[str] = []
|
|
if obj.image:
|
|
absolute = absolute_image_url(self, obj.image)
|
|
if absolute:
|
|
urls.append(absolute)
|
|
urls.extend(obj.image_urls or [])
|
|
return urls
|
|
|
|
def get_rating_distribution(self, obj: Flavor) -> dict[str, int]:
|
|
counts = dict.fromkeys((str(i) for i in range(1, 11)), 0)
|
|
for row in obj.ratings.values("score").annotate(c=Count("id")):
|
|
score = row["score"]
|
|
if 1 <= score <= 10:
|
|
counts[str(score)] = row["c"]
|
|
return counts
|
|
|
|
def get_user_rating(self, obj: Flavor) -> int | None:
|
|
request = self.context.get("request")
|
|
if request and request.user.is_authenticated:
|
|
try:
|
|
return request.user.ratings.get(flavor=obj).score
|
|
except Rating.DoesNotExist:
|
|
return None
|
|
return None
|