Django Serializer自定义邮箱校验信息不生效原因咨询
问题
我编写了如下的RegisterSerializer代码:
class RegisterSerializer(ModelSerializer): username = CharField(required=True) class Meta: model = User fields = ['username', 'password', 'email'] def create(self, validated_data): if User.objects.filter(username=validated_data['username']).exists(): raise ValidationError('ushbu username mavjud!') if User.objects.filter(email=validated_data['email']).exists(): raise ValidationError("ushbu email mavjud!") user = User.objects.create_user( username=validated_data['username'], password=validated_data['password'], email=validated_data['email'] ) return user
其中用户名的校验逻辑可以正常返回自定义错误信息,但邮箱的校验逻辑不生效,反而返回DRF默认提示:
"email": [ "user with this email already exists." ]
我期望使用序列化器内定义的校验错误信息,请问这是为什么?
原因
DRF的ModelSerializer会自动为模型中带有unique=True约束的字段生成UniqueValidator,这个校验器会在序列化器的validate阶段(也就是create方法执行之前)触发。
你的代码中:
- 显式声明了
username字段为CharField,但没有添加UniqueValidator,因此序列化器层面不会自动校验用户名唯一性,所以create方法里的自定义校验逻辑会执行。 - 没有显式声明
email字段,序列化器会根据User模型中email字段的unique=True约束自动添加UniqueValidator,并使用默认错误信息。这个内置校验会在create方法执行前就触发,导致你写的邮箱校验代码根本没机会运行。
解决方案
有两种常用的解决方式:
方式一:显式声明email字段,自定义UniqueValidator的错误信息
from rest_framework.validators import UniqueValidator class RegisterSerializer(ModelSerializer): username = CharField(required=True) email = CharField( required=True, validators=[UniqueValidator(queryset=User.objects.all(), message="ushbu email mavjud!")] ) class Meta: model = User fields = ['username', 'password', 'email'] def create(self, validated_data): # 此时用户名和邮箱的唯一性已由序列化器校验完成,可移除create内的重复校验 user = User.objects.create_user( username=validated_data['username'], password=validated_data['password'], email=validated_data['email'] ) return user
方式二:在序列化器的validate方法中统一处理校验
如果需要更自定义的校验逻辑,可以重写validate方法,同时注意要禁用自动生成的UniqueValidator:
class RegisterSerializer(ModelSerializer): username = CharField(required=True) # 显式声明email字段,不添加默认的UniqueValidator email = CharField(required=True) class Meta: model = User fields = ['username', 'password', 'email'] # 禁用自动生成的validators extra_kwargs = { 'email': {'validators': []}, 'username': {'validators': []} } def validate(self, data): if User.objects.filter(username=data['username']).exists(): raise ValidationError({'username': 'ushbu username mavjud!'}) if User.objects.filter(email=data['email']).exists(): raise ValidationError({'email': 'ushbu email mavjud!'}) return data def create(self, validated_data): user = User.objects.create_user( username=validated_data['username'], password=validated_data['password'], email=validated_data['email'] ) return user
注意:方式二中需要通过extra_kwargs禁用自动生成的validators,否则内置校验还是会先触发。
内容的提问来源于stack exchange,提问作者zavqiddin
相关产品推荐
相关产品推荐

