from rest_framework import serializers from .models import Group, Membership, Post from accounts.models import CustomUser, InterestTag from accounts.serializers import InterestTagSerializer as AccountsInterestTagSerializer # --- Minimal Serializers for nested representations --- class MinimalUserSerializer(serializers.ModelSerializer): avatar_url = serializers.SerializerMethodField() class Meta: model = CustomUser fields = ('id', 'nickname', 'avatar_url') def get_avatar_url(self, obj): request = self.context.get('request') if obj.avatar and hasattr(obj.avatar, 'url'): if request is not None: return request.build_absolute_uri(obj.avatar.url) return obj.avatar.url return None class MinimalGroupSerializer(serializers.ModelSerializer): class Meta: model = Group fields = ('id', 'name') # --- Main Serializers --- class GroupSerializer(serializers.ModelSerializer): creator = MinimalUserSerializer(read_only=True) members_count = serializers.IntegerField(source='members.count', read_only=True) tags = serializers.PrimaryKeyRelatedField( queryset=InterestTag.objects.all(), many=True, required=False, allow_empty=True ) tags_details = AccountsInterestTagSerializer(source='tags', many=True, read_only=True) cover_image = serializers.ImageField(max_length=None, use_url=True, required=False, allow_null=True) cover_image_url = serializers.SerializerMethodField(read_only=True) class Meta: model = Group fields = ( 'id', 'name', 'description', 'cover_image', 'cover_image_url', 'creator', 'members_count', 'tags', 'tags_details', 'created_at', 'updated_at' ) read_only_fields = ('id', 'created_at', 'updated_at', 'creator', 'members_count', 'tags_details', 'cover_image_url') def get_cover_image_url(self, obj): request = self.context.get('request') if obj.cover_image and hasattr(obj.cover_image, 'url'): if request is not None: return request.build_absolute_uri(obj.cover_image.url) return obj.cover_image.url return None def create(self, validated_data): tags_data = validated_data.pop('tags', None) group = super().create(validated_data) if tags_data is not None: group.tags.set(tags_data) return group def update(self, instance, validated_data): tags_data = validated_data.pop('tags', None) instance = super().update(instance, validated_data) if tags_data is not None: instance.tags.set(tags_data) return instance class MembershipSerializer(serializers.ModelSerializer): user = MinimalUserSerializer(read_only=True) group_id = serializers.IntegerField(source='group.id', read_only=True) group_name = serializers.CharField(source='group.name', read_only=True) class Meta: model = Membership fields = ('id', 'user', 'group_id', 'group_name', 'date_joined') read_only_fields = ('id', 'user', 'group_id', 'group_name', 'date_joined') class PostSerializer(serializers.ModelSerializer): # 经过再次修正和简化的 PostSerializer author = MinimalUserSerializer(read_only=True) # 作者信息只读,在GET时显示 group = MinimalGroupSerializer(read_only=True) # 小组信息只读,在GET时显示 class Meta: model = Post fields = ( 'id', 'group', # 在GET时显示小组信息 (只读) 'author', # 在GET时显示作者信息 (只读) 'title', 'content', # 'image', # 如果模型中有 image 字段,可以在这里添加用于上传 # 'image_url', # 如果模型中有 image 字段,可以添加 get_image_url 方法 'created_at', 'updated_at', ) # author 和 group 将在视图的 serializer.save() 中设置,所以它们对客户端来说是只读的 # title 和 content 是客户端在创建帖子时可以发送的 read_only_fields = ('id', 'author', 'group', 'created_at', 'updated_at') # create 方法不需要特别修改,因为 author 和 group 会在视图的 save() 中传入 # def create(self, validated_data): # # validated_data 只包含客户端发送的 title, content # # author 和 group 是通过 serializer.save(author=request.user, group=group) 传入的 # # ModelSerializer的默认create会将这些额外参数设置到模型实例上 # return super().create(validated_data) # 实际上,DRF的ModelSerializer在调用save时传递的额外关键字参数, # 会在模型实例被创建(通过调用模型的objects.create或类似方法)之前, # 被添加到传递给模型构造函数的关键字参数中。 # 所以,PostSerializer 的 create 方法可以保持默认,或者明确地像下面这样处理(如果需要更细致控制) # def create(self, validated_data): # # author 和 group 是从 serializer.save(author=..., group=...) 传递过来的 # # 它们现在应该在 validated_data 中,或者需要从 context 中获取 # # 更准确地说,它们会作为额外参数传递给模型的create方法 # # 保持默认的 super().create() 即可,只要视图的save()调用正确 # return super().create(validated_data) # 我们让 PostSerializer 的 create 方法保持默认,依赖视图的 serializer.save(author=..., group=...)