serializers.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from rest_framework import serializers
  2. from .models import Group, Membership, Post
  3. from accounts.models import CustomUser, InterestTag
  4. from accounts.serializers import InterestTagSerializer as AccountsInterestTagSerializer
  5. # --- Minimal Serializers for nested representations ---
  6. class MinimalUserSerializer(serializers.ModelSerializer):
  7. avatar_url = serializers.SerializerMethodField()
  8. class Meta:
  9. model = CustomUser
  10. fields = ('id', 'nickname', 'avatar_url')
  11. def get_avatar_url(self, obj):
  12. request = self.context.get('request')
  13. if obj.avatar and hasattr(obj.avatar, 'url'):
  14. if request is not None:
  15. return request.build_absolute_uri(obj.avatar.url)
  16. return obj.avatar.url
  17. return None
  18. class MinimalGroupSerializer(serializers.ModelSerializer):
  19. class Meta:
  20. model = Group
  21. fields = ('id', 'name')
  22. # --- Main Serializers ---
  23. class GroupSerializer(serializers.ModelSerializer):
  24. creator = MinimalUserSerializer(read_only=True)
  25. members_count = serializers.IntegerField(source='members.count', read_only=True)
  26. tags = serializers.PrimaryKeyRelatedField(
  27. queryset=InterestTag.objects.all(),
  28. many=True,
  29. required=False,
  30. allow_empty=True
  31. )
  32. tags_details = AccountsInterestTagSerializer(source='tags', many=True, read_only=True)
  33. cover_image = serializers.ImageField(max_length=None, use_url=True, required=False, allow_null=True)
  34. cover_image_url = serializers.SerializerMethodField(read_only=True)
  35. class Meta:
  36. model = Group
  37. fields = (
  38. 'id', 'name', 'description',
  39. 'cover_image', 'cover_image_url',
  40. 'creator', 'members_count',
  41. 'tags', 'tags_details',
  42. 'created_at', 'updated_at'
  43. )
  44. read_only_fields = ('id', 'created_at', 'updated_at', 'creator', 'members_count', 'tags_details', 'cover_image_url')
  45. def get_cover_image_url(self, obj):
  46. request = self.context.get('request')
  47. if obj.cover_image and hasattr(obj.cover_image, 'url'):
  48. if request is not None:
  49. return request.build_absolute_uri(obj.cover_image.url)
  50. return obj.cover_image.url
  51. return None
  52. def create(self, validated_data):
  53. tags_data = validated_data.pop('tags', None)
  54. group = super().create(validated_data)
  55. if tags_data is not None:
  56. group.tags.set(tags_data)
  57. return group
  58. def update(self, instance, validated_data):
  59. tags_data = validated_data.pop('tags', None)
  60. instance = super().update(instance, validated_data)
  61. if tags_data is not None:
  62. instance.tags.set(tags_data)
  63. return instance
  64. class MembershipSerializer(serializers.ModelSerializer):
  65. user = MinimalUserSerializer(read_only=True)
  66. group_id = serializers.IntegerField(source='group.id', read_only=True)
  67. group_name = serializers.CharField(source='group.name', read_only=True)
  68. class Meta:
  69. model = Membership
  70. fields = ('id', 'user', 'group_id', 'group_name', 'date_joined')
  71. read_only_fields = ('id', 'user', 'group_id', 'group_name', 'date_joined')
  72. class PostSerializer(serializers.ModelSerializer): # 经过再次修正和简化的 PostSerializer
  73. author = MinimalUserSerializer(read_only=True) # 作者信息只读,在GET时显示
  74. group = MinimalGroupSerializer(read_only=True) # 小组信息只读,在GET时显示
  75. class Meta:
  76. model = Post
  77. fields = (
  78. 'id',
  79. 'group', # 在GET时显示小组信息 (只读)
  80. 'author', # 在GET时显示作者信息 (只读)
  81. 'title',
  82. 'content',
  83. # 'image', # 如果模型中有 image 字段,可以在这里添加用于上传
  84. # 'image_url', # 如果模型中有 image 字段,可以添加 get_image_url 方法
  85. 'created_at',
  86. 'updated_at',
  87. )
  88. # author 和 group 将在视图的 serializer.save() 中设置,所以它们对客户端来说是只读的
  89. # title 和 content 是客户端在创建帖子时可以发送的
  90. read_only_fields = ('id', 'author', 'group', 'created_at', 'updated_at')
  91. # create 方法不需要特别修改,因为 author 和 group 会在视图的 save() 中传入
  92. # def create(self, validated_data):
  93. # # validated_data 只包含客户端发送的 title, content
  94. # # author 和 group 是通过 serializer.save(author=request.user, group=group) 传入的
  95. # # ModelSerializer的默认create会将这些额外参数设置到模型实例上
  96. # return super().create(validated_data)
  97. # 实际上,DRF的ModelSerializer在调用save时传递的额外关键字参数,
  98. # 会在模型实例被创建(通过调用模型的objects.create或类似方法)之前,
  99. # 被添加到传递给模型构造函数的关键字参数中。
  100. # 所以,PostSerializer 的 create 方法可以保持默认,或者明确地像下面这样处理(如果需要更细致控制)
  101. # def create(self, validated_data):
  102. # # author 和 group 是从 serializer.save(author=..., group=...) 传递过来的
  103. # # 它们现在应该在 validated_data 中,或者需要从 context 中获取
  104. # # 更准确地说,它们会作为额外参数传递给模型的create方法
  105. # # 保持默认的 super().create() 即可,只要视图的save()调用正确
  106. # return super().create(validated_data)
  107. # 我们让 PostSerializer 的 create 方法保持默认,依赖视图的 serializer.save(author=..., group=...)