from rest_framework import serializers from .models import Group, Membership, Post, Comment, PostLike # <<<< 导入 PostLike 模型 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) group = MinimalGroupSerializer(read_only=True) # 新增:点赞相关字段 likes_count = serializers.SerializerMethodField(read_only=True) is_liked_by_current_user = serializers.SerializerMethodField(read_only=True) class Meta: model = Post fields = ( 'id', 'group', 'author', 'title', 'content', 'created_at', 'updated_at', 'likes_count', # 新增 'is_liked_by_current_user', # 新增 ) read_only_fields = ( 'id', 'author', 'group', 'created_at', 'updated_at', 'likes_count', 'is_liked_by_current_user' # 新增的也设为只读 ) def get_likes_count(self, obj: Post) -> int: # obj 是 Post 实例 """获取帖子的总点赞数。""" return obj.likes.count() # obj.likes 是 PostLike 的 related_name def get_is_liked_by_current_user(self, obj: Post) -> bool: # obj 是 Post 实例 """检查当前用户是否已点赞该帖子。""" request = self.context.get('request') if not request or not request.user or not request.user.is_authenticated: return False # 未登录用户或匿名用户视为未点赞 # 检查是否存在当前用户对该帖子的点赞记录 return PostLike.objects.filter(post=obj, user=request.user).exists() class CommentSerializer(serializers.ModelSerializer): author = MinimalUserSerializer(read_only=True) post_id_display = serializers.IntegerField(source='post.id', read_only=True) post_title_display = serializers.CharField(source='post.title', read_only=True, allow_null=True) class Meta: model = Comment fields = ( 'id', 'post_id_display', 'post_title_display', 'author', 'content', 'created_at', 'updated_at', ) read_only_fields = ('id', 'author', 'post_id_display', 'post_title_display', 'created_at', 'updated_at') class PostLikeSerializer(serializers.ModelSerializer): # <<<< (可选) 新增 PostLikeSerializer user = MinimalUserSerializer(read_only=True) # 如果需要在点赞详情中显示帖子信息,可以添加 post 字段 # post = MinimalPostSerializer(read_only=True) # 假设有 MinimalPostSerializer post_id = serializers.IntegerField(source='post.id', read_only=True) class Meta: model = PostLike fields = ('id', 'user', 'post_id', 'created_at') read_only_fields = ('id', 'user', 'post_id', 'created_at')