mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 11:11:10 -05:00
220 lines
6.6 KiB
Python
220 lines
6.6 KiB
Python
"""
|
|
Serializers for ride review API endpoints.
|
|
|
|
This module contains serializers for ride review CRUD operations with Rich Choice Objects compliance.
|
|
"""
|
|
|
|
from rest_framework import serializers
|
|
from drf_spectacular.utils import extend_schema_field, extend_schema_serializer, OpenApiExample
|
|
from apps.rides.models.reviews import RideReview
|
|
from apps.accounts.models import User
|
|
from apps.core.choices.serializers import RichChoiceSerializer
|
|
|
|
|
|
class ReviewUserSerializer(serializers.ModelSerializer):
|
|
"""Serializer for user information in ride reviews."""
|
|
|
|
avatar_url = serializers.SerializerMethodField()
|
|
display_name = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = ["id", "username", "display_name", "avatar_url"]
|
|
read_only_fields = fields
|
|
|
|
@extend_schema_field(serializers.URLField(allow_null=True))
|
|
def get_avatar_url(self, obj):
|
|
"""Get the user's avatar URL."""
|
|
if hasattr(obj, "profile") and obj.profile:
|
|
return obj.profile.get_avatar_url()
|
|
return "/static/images/default-avatar.png"
|
|
|
|
@extend_schema_field(serializers.CharField())
|
|
def get_display_name(self, obj):
|
|
"""Get the user's display name."""
|
|
return obj.get_display_name()
|
|
|
|
|
|
@extend_schema_serializer(
|
|
examples=[
|
|
OpenApiExample(
|
|
name="Complete Ride Review",
|
|
summary="Full ride review response",
|
|
description="Example response showing all fields for a ride review",
|
|
value={
|
|
"id": 123,
|
|
"title": "Amazing roller coaster experience!",
|
|
"content": "This ride was absolutely incredible. The inversions were smooth and the theming was top-notch.",
|
|
"rating": 9,
|
|
"visit_date": "2023-06-15",
|
|
"created_at": "2023-06-16T10:30:00Z",
|
|
"updated_at": "2023-06-16T10:30:00Z",
|
|
"is_published": True,
|
|
"user": {
|
|
"id": 456,
|
|
"username": "coaster_fan",
|
|
"display_name": "Coaster Fan",
|
|
"avatar_url": "https://example.com/avatar.jpg"
|
|
},
|
|
"ride": {
|
|
"id": 789,
|
|
"name": "Steel Vengeance",
|
|
"slug": "steel-vengeance"
|
|
},
|
|
"park": {
|
|
"id": 101,
|
|
"name": "Cedar Point",
|
|
"slug": "cedar-point"
|
|
}
|
|
}
|
|
)
|
|
]
|
|
)
|
|
class RideReviewOutputSerializer(serializers.ModelSerializer):
|
|
"""Output serializer for ride reviews."""
|
|
|
|
user = ReviewUserSerializer(read_only=True)
|
|
|
|
# Ride information
|
|
ride = serializers.SerializerMethodField()
|
|
park = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = RideReview
|
|
fields = [
|
|
"id",
|
|
"title",
|
|
"content",
|
|
"rating",
|
|
"visit_date",
|
|
"created_at",
|
|
"updated_at",
|
|
"is_published",
|
|
"user",
|
|
"ride",
|
|
"park",
|
|
]
|
|
read_only_fields = [
|
|
"id",
|
|
"created_at",
|
|
"updated_at",
|
|
"user",
|
|
"ride",
|
|
"park",
|
|
]
|
|
|
|
@extend_schema_field(serializers.DictField())
|
|
def get_ride(self, obj):
|
|
"""Get ride information."""
|
|
return {
|
|
"id": obj.ride.id,
|
|
"name": obj.ride.name,
|
|
"slug": obj.ride.slug,
|
|
}
|
|
|
|
@extend_schema_field(serializers.DictField())
|
|
def get_park(self, obj):
|
|
"""Get park information."""
|
|
return {
|
|
"id": obj.ride.park.id,
|
|
"name": obj.ride.park.name,
|
|
"slug": obj.ride.park.slug,
|
|
}
|
|
|
|
|
|
class RideReviewCreateInputSerializer(serializers.ModelSerializer):
|
|
"""Input serializer for creating ride reviews."""
|
|
|
|
class Meta:
|
|
model = RideReview
|
|
fields = [
|
|
"title",
|
|
"content",
|
|
"rating",
|
|
"visit_date",
|
|
]
|
|
|
|
def validate_rating(self, value):
|
|
"""Validate rating is between 1 and 10."""
|
|
if not (1 <= value <= 10):
|
|
raise serializers.ValidationError("Rating must be between 1 and 10.")
|
|
return value
|
|
|
|
|
|
class RideReviewUpdateInputSerializer(serializers.ModelSerializer):
|
|
"""Input serializer for updating ride reviews."""
|
|
|
|
class Meta:
|
|
model = RideReview
|
|
fields = [
|
|
"title",
|
|
"content",
|
|
"rating",
|
|
"visit_date",
|
|
]
|
|
|
|
def validate_rating(self, value):
|
|
"""Validate rating is between 1 and 10."""
|
|
if not (1 <= value <= 10):
|
|
raise serializers.ValidationError("Rating must be between 1 and 10.")
|
|
return value
|
|
|
|
|
|
class RideReviewListOutputSerializer(serializers.ModelSerializer):
|
|
"""Simplified output serializer for ride review lists."""
|
|
|
|
user = ReviewUserSerializer(read_only=True)
|
|
ride_name = serializers.CharField(source="ride.name", read_only=True)
|
|
park_name = serializers.CharField(source="ride.park.name", read_only=True)
|
|
|
|
class Meta:
|
|
model = RideReview
|
|
fields = [
|
|
"id",
|
|
"title",
|
|
"rating",
|
|
"visit_date",
|
|
"created_at",
|
|
"is_published",
|
|
"user",
|
|
"ride_name",
|
|
"park_name",
|
|
]
|
|
read_only_fields = fields
|
|
|
|
|
|
class RideReviewStatsOutputSerializer(serializers.Serializer):
|
|
"""Output serializer for ride review statistics."""
|
|
|
|
total_reviews = serializers.IntegerField()
|
|
published_reviews = serializers.IntegerField()
|
|
pending_reviews = serializers.IntegerField()
|
|
average_rating = serializers.FloatField(allow_null=True)
|
|
rating_distribution = serializers.DictField(
|
|
child=serializers.IntegerField(),
|
|
help_text="Count of reviews by rating (1-10)"
|
|
)
|
|
recent_reviews = serializers.IntegerField()
|
|
|
|
|
|
class RideReviewModerationInputSerializer(serializers.Serializer):
|
|
"""Input serializer for review moderation operations."""
|
|
|
|
review_ids = serializers.ListField(
|
|
child=serializers.IntegerField(),
|
|
help_text="List of review IDs to moderate"
|
|
)
|
|
action = serializers.ChoiceField(
|
|
choices=[
|
|
("publish", "Publish"),
|
|
("unpublish", "Unpublish"),
|
|
("delete", "Delete"),
|
|
],
|
|
help_text="Moderation action to perform"
|
|
)
|
|
moderation_notes = serializers.CharField(
|
|
required=False,
|
|
allow_blank=True,
|
|
help_text="Optional notes about the moderation action"
|
|
)
|