serializers.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from rest_framework import serializers
  2. from .models import CustomUser # 导入你的 CustomUser 模型
  3. from django.contrib.auth.password_validation import validate_password # Django 自带密码验证
  4. # from django.core.exceptions import ValidationError # 如果需要在 validate 方法中手动抛出
  5. class UserRegistrationSerializer(serializers.ModelSerializer):
  6. password = serializers.CharField(
  7. write_only=True,
  8. required=True,
  9. validators=[validate_password],
  10. style={'input_type': 'password'} # 在DRF的可浏览API中显示为密码输入框
  11. )
  12. password2 = serializers.CharField(
  13. write_only=True,
  14. required=True,
  15. label="确认密码", # 在DRF的可浏览API中的标签
  16. style={'input_type': 'password'}
  17. )
  18. # 如果avatar是注册时可选上传的,确保在Meta中处理
  19. avatar = serializers.ImageField(required=False, allow_null=True, max_length=None, use_url=True)
  20. class Meta:
  21. model = CustomUser
  22. # 列出注册时需要用户提供的字段
  23. # 确保这些字段与 CustomUser 模型中定义的一致,特别是 USERNAME_FIELD 和 REQUIRED_FIELDS
  24. fields = ('email', 'phone_number', 'nickname', 'password', 'password2', 'school', 'bio', 'avatar')
  25. extra_kwargs = {
  26. # password 和 password2 已经在上面定义了 write_only=True
  27. 'nickname': {'required': True}, # 根据你的 CustomUser.REQUIRED_FIELDS,nickname是必填
  28. 'school': {'required': False, 'allow_blank': True},
  29. 'bio': {'required': False, 'allow_blank': True},
  30. # 'avatar': {'required': False} # 已经在上面字段定义中处理
  31. }
  32. def validate(self, attrs):
  33. if attrs['password'] != attrs['password2']:
  34. raise serializers.ValidationError({"password2": "两次输入的密码不匹配。"}) # 将错误关联到password2字段
  35. return attrs
  36. def create(self, validated_data):
  37. validated_data.pop('password2') # 移除 password2,它不需要保存到模型
  38. # 使用 CustomUser 模型的 create_user 方法创建用户
  39. # 它会处理密码哈希
  40. # validated_data 现在包含了 'email', 'phone_number', 'password', 'nickname' 以及可选的 'school', 'bio', 'avatar'
  41. user = CustomUser.objects.create_user(**validated_data)
  42. return user
  43. class UserProfileSerializer(serializers.ModelSerializer):
  44. """
  45. 用于获取和更新用户个人资料的序列化器。
  46. """
  47. avatar_url = serializers.SerializerMethodField() # 用于获取完整的头像URL
  48. class Meta:
  49. model = CustomUser
  50. # 列出用户可以查看和修改的字段
  51. # 不应包含敏感信息如 password (除非是 write_only 用于修改密码的特殊场景)
  52. fields = (
  53. 'id', 'email', 'phone_number', 'nickname',
  54. 'avatar', 'avatar_url', 'bio', 'school',
  55. 'date_joined', 'last_login', 'is_active' # is_active 可以考虑是否允许用户自己修改
  56. )
  57. # 定义只读字段 (在更新时不能被修改,或者需要特殊流程)
  58. read_only_fields = ('id', 'email', 'phone_number', 'date_joined', 'last_login', 'avatar_url')
  59. # avatar 字段本身可以用于上传,所以不是read_only,但 avatar_url 是只读的。
  60. # email 和 phone_number 通常不应通过这个接口随意更改,如果允许更改,需要额外的验证流程(比如发送验证码)。
  61. def get_avatar_url(self, obj):
  62. request = self.context.get('request')
  63. if obj.avatar and hasattr(obj.avatar, 'url'):
  64. if request is not None:
  65. return request.build_absolute_uri(obj.avatar.url)
  66. return obj.avatar.url # Fallback if request is not available
  67. return None # 如果没有头像或无法获取URL
  68. # 如果允许通过这个Serializer更新头像,不需要特别做什么,DRF的ModelSerializer会自动处理ImageField
  69. # 确保在视图中传递 request 到 serializer context,以便生成完整的URL