from rest_framework import serializers from .models import Competition, CompetitionEnrollment, ScoreDimension, Project, ProjectFile, Score, Comment from shop.serializers import WeChatUserSerializer import uuid 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): if obj.cover_image: return obj.cover_image.url return obj.cover_image_url class CompetitionEnrollmentSerializer(serializers.ModelSerializer): user = WeChatUserSerializer(read_only=True) competition_title = serializers.SerializerMethodField() class Meta: model = CompetitionEnrollment fields = ['id', 'competition', 'competition_title', 'user', 'role', 'status', 'created_at'] read_only_fields = ['status'] def get_competition_title(self, obj): return obj.competition.title if obj.competition else '' class ProjectFileSerializer(serializers.ModelSerializer): file_url_display = serializers.SerializerMethodField() file_size_display = serializers.SerializerMethodField() class Meta: model = ProjectFile fields = ['id', 'project', 'file_type', 'file', 'file_url', 'file_size', 'name', 'created_at', 'file_url_display', 'file_size_display'] def get_file_url_display(self, obj): if obj.file: return obj.file.url return obj.file_url def get_file_size_display(self, obj): if not obj.file_size: return None size = obj.file_size if size < 1024: return f"{size} B" elif size < 1024 * 1024: return f"{size / 1024:.1f} KB" elif size < 1024 * 1024 * 1024: return f"{size / (1024 * 1024):.1f} MB" else: return f"{size / (1024 * 1024 * 1024):.2f} GB" def validate_file(self, value): if not value: return value limit_mb = 50 if value.size > limit_mb * 1024 * 1024: raise serializers.ValidationError(f"文件大小不能超过 {limit_mb}MB") return value def create(self, validated_data): from django.conf import settings from shop.utils import get_current_wechat_user request = self.context.get('request') user = get_current_wechat_user(request) if request else None print(f"=== File Upload Debug ===") print(f"User: {user}") print(f"Validated data keys: {validated_data.keys()}") file_obj = validated_data.get('file') if file_obj: print(f"File name: {file_obj.name}, size: {file_obj.size}") ext = file_obj.name.split('.')[-1].lower() if '.' in file_obj.name else '' if ext in ['ppt', 'pptx']: validated_data['file_type'] = 'ppt' elif ext == 'pdf': validated_data['file_type'] = 'pdf' elif ext in ['jpg', 'jpeg', 'png', 'gif', 'webp']: validated_data['file_type'] = 'image' elif ext in ['mp4', 'mov', 'avi', 'webm']: validated_data['file_type'] = 'video' elif ext in ['doc', 'docx']: validated_data['file_type'] = 'doc' if not validated_data.get('name'): validated_data['name'] = file_obj.name validated_data['file_size'] = file_obj.size try: from ai_services.services import AliyunTingwuService service = AliyunTingwuService() if service.bucket: project = validated_data.get('project') file_name = f"competitions/projects/{project.id}/{uuid.uuid4()}.{ext}" oss_url = service.upload_to_oss(file_obj, file_name, day=30) validated_data['file_url'] = oss_url validated_data['file'] = None print(f"OSS upload success: {oss_url}") else: print("OSS bucket is None, OSS not configured properly") except Exception as e: print(f"OSS upload failed in serializer: {e}") return super().create(validated_data) 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