serializers.py序列化器文件中def validate(self, attrs)方法的attrs和def create(self, validated_data)方法的validated_data 两者之间的关联关系,以及他们各自的使用方式
serializers.py文件内容:
from rest_framework import serializers
class RegisterModelSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(label='确认密码', help_text='请输入确认密码',
write_only=True, min_length=6, max_length=20,
error_messages={
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
})
class Meta:
model = User
# fields 决定了哪些字段会参与序列化和反序列化,决定了序列化输出给前端的参数有哪些,
# 以及决定了反序列化输入时入库的参数有哪些。
fields = ['id', 'username', 'password', 'password_confirm', 'email', 'mobile']
# 修改模型字段的参数
extra_kwargs = {
'username': {
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的用户名',
'max_length': '仅允许6-20个字符的用户名',
}
},
'mobile': {
'required': True,
'error_messages': {
'required': '必须传递手机号'
}
},
'password': {
'min_length': 6,
'max_length': 20,
'write_only': True,
'error_messages': {
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
}
},
'email': {
'required': True,
'validators': [UniqueValidator(queryset=model.objects.all(), message='此邮箱已经注册')]
}
}
def validate(self, attrs):
# validate函数中的attrs时,前端传递过来的参数。
password = attrs.get('password')
password_confirm = attrs.pop('password_confirm')
if password_confirm != password:
raise serializers.ValidationError('密码与确认密码不一致')
return attrs
def create(self, validated_data):
"""
# 创建入库,validated_data 是attrs经过validate方法校验、处理后的最终数据,
是drf序列化器执行流程中【校验-处理-创建】的关键数据传递链路
"""
# 方式一:
# password = validated_data.get('password')
# password = make_password(password)
# validated_data['password'] = password
# return super().create(validated_data)
# 方式二:
# instance: User = super().create(validated_data)
# instance.set_password(instance.password)
# instance.save()
# return instance
# 方式三:
return User.objects.create_user(**validated_data)
validate(self, attrs) 中的 attrs 和 create(self, validated_data) 中的 validated_data 之间的关系,以及它们各自的使用方式 —— 核心结论是:validated_data 是 attrs 经过 validate 方法校验、处理后的最终数据,是 DRF 序列化器执行流程中 “校验→处理→创建” 的关键数据传递链路。
下面我会拆解这个流程,结合你的代码详细说明两者的关系和使用场景。
一、先明确核心概念

二、DRF 序列化器的执行流程(关键)
这是理解两者关系的核心,你的注册序列化器执行流程如下:






你的代码中两者的具体使用示例
1.attrs 的使用(validate 方法):
def validate(self, attrs):
# 1. 从attrs中取出需要校验的字段
password = attrs.get('password')
password_confirm = attrs.pop('password_confirm') # 取出并移除非模型字段
# 2. 跨字段校验(核心场景)
if password_confirm != password:
raise serializers.ValidationError('密码与确认密码不一致')
# 3. 返回处理后的attrs(成为后续的validated_data)
return attrs
✅ 典型场景:跨字段校验(密码 + 确认密码)、移除非模型字段、数据格式化(比如手机号去空格)。
2.validated_data 的使用(create 方法):
def create(self, validated_data):
# 直接使用校验后的干净数据创建用户
return User.objects.create_user(**validated_data)
✅ 典型场景:解包传入模型的创建方法(create_user/create)、给模型字段赋值、额外的入库逻辑(如密码加密)。
四、常见易错点提醒
1.不要在 create 方法中做校验:
校验逻辑必须放在 validate 方法中,create 只负责创建实例 —— 如果在 create 中发现数据错误,抛出的异常无法被 DRF 标准化处理,前端会收到不友好的 500 错误。
2.validate 方法必须返回字典:
如果你在 validate 中修改了 attrs,最后一定要 return attrs(或处理后的字典),否则 validated_data 会是空的,导致创建实例失败。
3.非模型字段必须在 validate 中移除:
比如你的 password_confirm 是自定义字段(User 模型没有),如果不通过 attrs.pop() 移除,后续调用 create_user 时会因为 “未知关键字参数” 报错。
总结
关系:validated_data 是 attrs 经过 validate 方法校验、处理后的 “最终版数据”,是 DRF 序列化器从 “校验” 到 “创建” 的核心数据传递链路;
attrs 用法:在 validate 中做跨字段校验、移除非模型字段、数据预处理;
validated_data 用法:在 create 中直接用于模型实例创建,无需再做校验,保证数据安全入库。
简单记:attrs 是 “待加工的原料”,validated_data 是 “加工完成的成品”,validate 是 “加工厂”,create 是 “成品使用环节”。

浙公网安备 33010602011771号