from rest_framework import serializers from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment, HomePageConfig, CarouselItem from shop.serializers import WeChatUserSerializer class CarouselItemSerializer(serializers.ModelSerializer): display_image = serializers.SerializerMethodField() class Meta: model = CarouselItem fields = ['id', 'carousel_type', 'image', 'image_url', 'display_image', 'title', 'subtitle', 'status', 'status_color', 'date', 'location', 'order', 'is_active'] def get_display_image(self, obj): request = self.context.get('request') if obj.image: if request: return request.build_absolute_uri(obj.image.url) return obj.image.url return obj.image_url class HomePageConfigSerializer(serializers.ModelSerializer): display_banner = serializers.SerializerMethodField() carousel1_items = serializers.SerializerMethodField() carousel2_items = serializers.SerializerMethodField() class Meta: model = HomePageConfig fields = ['id', 'banner_image', 'banner_image_url', 'display_banner', 'main_title', 'carousel1_title', 'carousel2_title', 'organizer', 'undertaker', 'carousel1_items', 'carousel2_items'] def get_display_banner(self, obj): request = self.context.get('request') if obj.banner_image: if request: return request.build_absolute_uri(obj.banner_image.url) return obj.banner_image.url return obj.banner_image_url def get_carousel1_items(self, obj): items = CarouselItem.objects.filter(carousel_type='carousel1', is_active=True) return CarouselItemSerializer(items, many=True, context=self.context).data def get_carousel2_items(self, obj): items = CarouselItem.objects.filter(carousel_type='carousel2', is_active=True) return CarouselItemSerializer(items, many=True, context=self.context).data class ScoreDimensionSerializer(serializers.ModelSerializer): class Meta: model = ScoreDimension fields = ['id', 'name', 'description', 'weight', 'max_score', 'order'] class CompetitionSerializer(serializers.ModelSerializer): score_dimensions = ScoreDimensionSerializer(many=True, read_only=True) display_cover_image = serializers.SerializerMethodField() status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = Competition fields = ['id', 'title', 'description', 'rule_description', 'condition_description', 'cover_image', 'cover_image_url', 'display_cover_image', 'start_time', 'end_time', 'status', 'project_visibility', 'status_display', 'is_active', 'score_dimensions', 'created_at'] def get_display_cover_image(self, obj): request = self.context.get('request') if obj.cover_image: if request: return request.build_absolute_uri(obj.cover_image.url) return obj.cover_image.url return obj.cover_image_url class CompetitionEnrollmentSerializer(serializers.ModelSerializer): user = WeChatUserSerializer(read_only=True) class Meta: model = CompetitionEnrollment fields = ['id', 'competition', 'user', 'role', 'status', 'created_at'] read_only_fields = ['status'] class ProjectFileSerializer(serializers.ModelSerializer): class Meta: model = ProjectFile fields = ['id', 'project', 'file_type', 'file', 'file_url', 'name', 'created_at'] def validate_file(self, value): if not value: return value # 50MB limit limit_mb = 50 if value.size > limit_mb * 1024 * 1024: raise serializers.ValidationError(f"文件大小不能超过 {limit_mb}MB") return value class ProjectSerializer(serializers.ModelSerializer): files = ProjectFileSerializer(many=True, read_only=True) contestant_info = serializers.SerializerMethodField() display_cover_image = serializers.SerializerMethodField() class Meta: model = Project fields = ['id', 'competition', 'contestant', 'title', 'description', 'team_info', 'cover_image', 'cover_image_url', 'display_cover_image', 'status', 'final_score', 'files', 'contestant_info', 'created_at'] read_only_fields = ['final_score', 'contestant'] def get_contestant_info(self, obj): return { "nickname": obj.contestant.user.nickname, "avatar_url": obj.contestant.user.avatar_url } def get_display_cover_image(self, obj): if obj.cover_image: return obj.cover_image.url return obj.cover_image_url class ScoreSerializer(serializers.ModelSerializer): judge_name = serializers.CharField(source='judge.user.nickname', read_only=True) dimension_name = serializers.CharField(source='dimension.name', read_only=True) class Meta: model = Score fields = ['id', 'project', 'judge', 'dimension', 'score', 'judge_name', 'dimension_name', 'created_at'] read_only_fields = ['judge'] class CommentSerializer(serializers.ModelSerializer): judge_name = serializers.CharField(source='judge.user.nickname', read_only=True) score = serializers.SerializerMethodField() class Meta: model = Comment fields = ['id', 'project', 'judge', 'content', 'judge_name', 'created_at', 'score'] read_only_fields = ['judge'] def get_score(self, obj): scores = Score.objects.filter(project=obj.project, judge=obj.judge) if not scores.exists(): return None current_judge_total_score = 0 current_judge_total_weight = 0 for score in scores: current_judge_total_score += score.score * score.dimension.weight current_judge_total_weight += score.dimension.weight if current_judge_total_weight > 0: judge_score = current_judge_total_score / current_judge_total_weight return round(judge_score, 1) return None