首页 > 解决方案 > DRF 验证器在唯一性检查时不返回 false

问题描述

我在 DRF 中有一个用户序列化程序,如下所示:

class UserSerializer(serializers.ModelSerializer):

    class Meta:  # password should exist only if POST
        model = User
        fields = ['first_name', 'last_name',
                  'password', 'email', 'username']

        write_only_fields = ['password']

这就是我检查外壳时的样子。

UserSerializer():
    first_name = CharField(allow_blank=True, max_length=30, required=False)
    last_name = CharField(allow_blank=True, max_length=150, required=False)
    password = CharField(max_length=128)
    email = EmailField(allow_blank=True, label='Email address', max_length=254, required=False)
    username = CharField(help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, validators=[<django.contrib.auth.validators.UnicodeUsernameValidator object>, <UniqueValidator(queryset=User.objects.all())>])

在我看来,如果我is_valid()使用数据库中已经存在的数据检查序列化程序,该函数在应该返回 False 时返回 True,然后引发 django 错误:

django.db.utils.IntegrityError: duplicate key value violates unique constraint "auth_user_username_key"
DETAIL:  Key (username)=(myrandomusername) already exists.

为什么会这样?

标签: pythondjangodjango-rest-framework

解决方案


序列化器不关心底层是否有异常,只关心序列化/反序列化。username因此,当您在已经存在的 POST 中传递 a时,IntegrityError会在模型层(在序列化程序传递数据之后)而不是在序列化程序上引发,因此它不知道。

序列化程序仅检查反序列化是否正确进行,即您传递的所有数据都符合序列化程序中字段的定义。如果它们是有效的,它将传递到下一步。

此外,Serializer.is_valid仅处理ValidationError,并保留字典以引用错误。对于错误,它决定是否引发ValidationError(从错误中)基于raise_exception.


您应该查看create序列化程序(ModelSerializer和子类)的方法来处理数据库级异常,因为所有对象创建逻辑ModelSerializer都在其中。(另请查看update更新方法)。

DRF 提供ModelSerializer了确保从反序列化数据创建和更新模型对象的功能,它应该被视为对基本序列化程序定义的扩展。


推荐阅读