- Coaster editor: name input in top bar, saved/loaded with coaster data - CoasterListPanel: show coaster name prominently alongside creator username - ChallengesListPanel: drill-in detail view with center map, plan coaster, and accept challenge buttons; coaster count shown in list and detail - AllCoastersPanel: coaster count visible in challenge entries - Backend: add coaster_count to ChallengeMapSerializer and ChallengeDetailSerializer - Fix: ChallengeLayer and ChallengesListPanel were reading f.properties.id (always undefined) instead of f.id — GeoFeatureModelSerializer puts the pk at the GeoJSON Feature level, not in properties - Types: remove id from ChallengeMapProperties to reflect actual data shape Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
36 lines
1.2 KiB
Python
36 lines
1.2 KiB
Python
from rest_framework import serializers
|
|
from .models import Coaster
|
|
|
|
|
|
class CoasterSerializer(serializers.ModelSerializer):
|
|
creator_username = serializers.ReadOnlyField(source='creator.username')
|
|
rating_avg = serializers.SerializerMethodField()
|
|
rating_count = serializers.SerializerMethodField()
|
|
user_rating = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Coaster
|
|
fields = [
|
|
'id', 'creator_username', 'challenge', 'name',
|
|
'anchors', 'acceleration_strips',
|
|
'rating_avg', 'rating_count', 'user_rating',
|
|
'created_at', 'updated_at',
|
|
]
|
|
read_only_fields = ['id', 'creator_username', 'created_at', 'updated_at']
|
|
|
|
def get_rating_avg(self, obj):
|
|
ratings = list(obj.ratings.values_list('rating', flat=True))
|
|
if not ratings:
|
|
return None
|
|
return round(sum(ratings) / len(ratings), 2)
|
|
|
|
def get_rating_count(self, obj):
|
|
return obj.ratings.count()
|
|
|
|
def get_user_rating(self, obj):
|
|
request = self.context.get('request')
|
|
if not request or not request.user.is_authenticated:
|
|
return None
|
|
rating = obj.ratings.filter(user=request.user).first()
|
|
return rating.rating if rating else None
|