验证唯一的电子邮件django rest框架序列化程序

时间:2020-09-23 13:51:15

标签: django django-rest-framework django-serializer

我有一个模型,其中“电子邮件”字段是唯一的。我认为这会使每封电子邮件都变为小写字母,因为它在User实例上具有normalize_email()方法。但是,它仅规范化域部分,因此,如果company@gmail.com存在,则Company@gmail.com被认为是唯一的。因此,我决定在序列化程序中创建validate_email()以始终返回小写电子邮件。这是一个字段验证,并在文档中进行了描述。

    def validate_email(self, value):
        return value.lower()

但是,看起来此方法在序列化程序检查数据库中是否存在值之后返回该值。这是一个示例:

如果我尝试使用user@gmail.com创建一个用户,并且该用户已经存在,则它将返回“用户已经存在”。但是,如果我使用User@gmail.com运行,它将首先运行SQL请求并检查User@gmail.com!= user@gmail.com,之后,它将尝试使用user@gmail.com创建新实例。因为它是从validate_email()返回的,而IntegrityError将被引发,因为它变成了已经在数据库中的user@gmail.com!

我可以做类似的事情

    def validate_email(self, value):
        norm_email = value.lower()
        if User.objects.filter(email=norm_email).exists():
            raise serializers.ValidationError("Not unique email")
        return norm_email

但这是对数据库的另一个请求,我不想要它。

所以我的问题是,哪种方法运行SQL请求以检查DB中的唯一性?这样我就可以覆盖它并传递已经小写的值?

1 个答案:

答案 0 :(得分:1)

使用iexact--(django doc)查找

transparent

更新

在内部进行DRF查询以检查唯一约束,因为在模型字段中,我们设置了 User.objects.filter(email__iexact=norm_email).exists() 。为了避免这种情况,我们需要在序列化程序中明确定义unique=True字段 ,该字段 绕过 唯一检查验证

email

Django shell输出

class UserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField()

    def validate_email(self, value):
        lower_email = value.lower()
        if User.objects.filter(email__iexact=lower_email).exists():
            raise serializers.ValidationError("Duplicate")
        return lower_email

    class Meta:
        model = User
        fields = ('email',)