from adrf.serializers import ( ModelSerializer, CharField, ImageField, DateTimeField, ListField, FileField, SerializerMethodField, ) from rest_framework.exceptions import ValidationError from .models import ( BugReport, BugReportImage, BugReportAttachment, BugReportComment, BugReportCommentImage, BugReportCommentAttachment ) class BugReportImageSerializer(ModelSerializer): class Meta: model = BugReportImage fields = ['id', 'image', 'created_at'] class BugReportAttachmentSerializer(ModelSerializer): class Meta: model = BugReportAttachment fields = ['id', 'file', 'filename', 'file_size', 'created_at'] class BugReportCommentImageSerializer(ModelSerializer): class Meta: model = BugReportCommentImage fields = ['id', 'image', 'created_at'] class BugReportCommentAttachmentSerializer(ModelSerializer): class Meta: model = BugReportCommentAttachment fields = ['id', 'file', 'filename', 'file_size', 'created_at'] class BugReportCommentSerializer(ModelSerializer): user_name = CharField(source='user.nickname', read_only=True) user_avatar = ImageField(source='user.avatar', read_only=True) images = BugReportCommentImageSerializer(many=True, read_only=True) attachments = BugReportCommentAttachmentSerializer(many=True, read_only=True) created_at = DateTimeField(format='%Y-%m-%d %H:%M') class Meta: model = BugReportComment fields = [ 'id', 'user', 'user_name', 'user_avatar', 'content', 'is_admin', 'created_at', 'images', 'attachments' ] read_only_fields = ['user', 'is_admin'] class BugReportListSerializer(ModelSerializer): user_name = CharField(source='user.nickname', read_only=True) images_count = SerializerMethodField() class Meta: model = BugReport fields = [ 'id', 'title', 'bug_type', 'priority', 'status', 'created_at', 'updated_at', 'user_name', 'images_count' ] async def get_images_count(self, obj): return await obj.images.acount() class BugReportDetailSerializer(ModelSerializer): user_name = CharField(source='user.nickname', read_only=True) user_avatar = ImageField(source='user.avatar', read_only=True) images = BugReportImageSerializer(many=True, read_only=True) attachments = BugReportAttachmentSerializer(many=True, read_only=True) comments = BugReportCommentSerializer(many=True, read_only=True) class Meta: model = BugReport fields = [ 'id', 'title', 'bug_type', 'priority', 'status', 'description', 'created_at', 'updated_at', 'user', 'user_name', 'user_avatar', 'images', 'attachments', 'comments' ] read_only_fields = ['user', 'status'] class BugReportCreateSerializer(ModelSerializer): images = ListField( child=ImageField(), required=False, max_length=5 ) attachments = ListField( child=FileField(), required=False, max_length=3 ) class Meta: model = BugReport fields = ['title', 'bug_type', 'priority', 'description', 'images', 'attachments'] def validate_images(self, value): max_size = 10 * 1024 * 1024 # 10MB for image in value: if image.size > max_size: raise ValidationError(f"图片 {image.name} 大小超过10MB限制") return value def validate_attachments(self, value): max_size = 20 * 1024 * 1024 # 20MB for attachment in value: if attachment.size > max_size: raise ValidationError(f"附件 {attachment.name} 大小超过20MB限制") return value async def acreate(self, validated_data): images_data = validated_data.pop('images', []) attachments_data = validated_data.pop('attachments', []) bug_report = await BugReport.objects.acreate(**validated_data) for image in images_data: await BugReportImage.objects.acreate(bug_report=bug_report, image=image) for attachment in attachments_data: await BugReportAttachment.objects.acreate( bug_report=bug_report, file=attachment, filename=attachment.name, file_size=attachment.size ) return bug_report class BugReportCommentCreateSerializer(ModelSerializer): images = ListField( child=ImageField(), required=False, max_length=3 ) attachments = ListField( child=FileField(), required=False, max_length=2 ) class Meta: model = BugReportComment fields = ['content', 'images', 'attachments'] def validate_images(self, value): max_size = 10 * 1024 * 1024 # 10MB for image in value: if image.size > max_size: raise ValidationError(f"图片 {image.name} 大小超过10MB限制") return value def validate_attachments(self, value): max_size = 20 * 1024 * 1024 # 20MB for attachment in value: if attachment.size > max_size: raise ValidationError(f"附件 {attachment.name} 大小超过20MB限制") return value async def acreate(self, validated_data): images_data = validated_data.pop('images', []) attachments_data = validated_data.pop('attachments', []) comment = await BugReportComment.objects.acreate(**validated_data) for image in images_data: await BugReportCommentImage.objects.acreate(comment=comment, image=image) for attachment in attachments_data: await BugReportCommentAttachment.objects.acreate( comment=comment, file=attachment, filename=attachment.name, file_size=attachment.size ) return comment