103 lines
3.4 KiB
Python
103 lines
3.4 KiB
Python
from rest_framework import serializers
|
|
from rest_framework_gis.fields import GeometryField
|
|
from rest_framework_gis.serializers import GeoFeatureModelSerializer
|
|
|
|
from apps.utils.storage import preview_url
|
|
from .models import Challenge, ChallengeParticipant
|
|
|
|
|
|
class ChallengeCreateSerializer(serializers.ModelSerializer):
|
|
# Accepts GeoJSON Polygon from the client
|
|
region = GeometryField(precision=6)
|
|
|
|
class Meta:
|
|
model = Challenge
|
|
fields = ["title", "description", "region", "max_submissions", "expires_at"]
|
|
|
|
def validate_region(self, value):
|
|
if value.geom_type != "Polygon":
|
|
raise serializers.ValidationError("region must be a GeoJSON Polygon.")
|
|
return value
|
|
|
|
|
|
class ChallengeUpdateSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Challenge
|
|
fields = ["title", "description", "expires_at", "status"]
|
|
|
|
|
|
class ChallengeMapSerializer(GeoFeatureModelSerializer):
|
|
"""
|
|
GeoJSON FeatureCollection using region_centroid as geometry.
|
|
Used for the map pin list — does not include the full region polygon.
|
|
"""
|
|
|
|
class Meta:
|
|
model = Challenge
|
|
geo_field = "region_centroid"
|
|
fields = [
|
|
"id", "title", "status",
|
|
"submission_count", "max_submissions",
|
|
"expires_at", "created_at",
|
|
]
|
|
|
|
|
|
class ChallengeSplatPreviewSerializer(serializers.Serializer):
|
|
id = serializers.UUIDField()
|
|
preview_url = serializers.SerializerMethodField()
|
|
created_at = serializers.DateTimeField()
|
|
|
|
def get_preview_url(self, obj):
|
|
return preview_url(obj.preview_key)
|
|
|
|
|
|
class ChallengeDetailSerializer(serializers.ModelSerializer):
|
|
region = serializers.SerializerMethodField()
|
|
region_centroid = serializers.SerializerMethodField()
|
|
creator_username = serializers.CharField(source="creator.username", read_only=True)
|
|
participant_count = serializers.SerializerMethodField()
|
|
is_participating = serializers.SerializerMethodField()
|
|
preview_splats = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Challenge
|
|
fields = [
|
|
"id", "title", "description", "status",
|
|
"creator_username",
|
|
"region", "region_centroid",
|
|
"max_submissions", "submission_count",
|
|
"participant_count", "is_participating",
|
|
"preview_splats",
|
|
"expires_at", "created_at", "updated_at",
|
|
]
|
|
|
|
def get_region(self, obj):
|
|
return obj.region.geojson if obj.region else None
|
|
|
|
def get_region_centroid(self, obj):
|
|
return obj.region_centroid.geojson if obj.region_centroid else None
|
|
|
|
def get_participant_count(self, obj):
|
|
return obj.participants.count()
|
|
|
|
def get_is_participating(self, obj):
|
|
request = self.context.get("request")
|
|
if not request or not request.user.is_authenticated:
|
|
return False
|
|
return obj.participants.filter(user=request.user).exists()
|
|
|
|
def get_preview_splats(self, obj):
|
|
from apps.splats.models import Splat
|
|
qs = (
|
|
Splat.objects.filter(challenge=obj, is_published=True)
|
|
.order_by("-created_at")[:5]
|
|
)
|
|
return ChallengeSplatPreviewSerializer(qs, many=True).data
|
|
|
|
|
|
class ChallengeParticipantSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = ChallengeParticipant
|
|
fields = ["id", "joined_at"]
|
|
read_only_fields = fields
|