123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- 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')
|