DRF验证程序在唯一性检查时不会返回false

时间:2019-11-09 13:57:19

标签: python django django-rest-framework

我在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.

为什么会这样?

1 个答案:

答案 0 :(得分:0)

Serializer不在乎较低级别是否存在异常,它仅在乎序列化/反序列化。因此,当您在已存在的POST中传递username时,IntegrityError在模型层(在序列化器传递数据之后)而不是在序列化器上引发,因此不知道它。

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

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


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

DRF提供ModelSerializer以确保从反序列化数据创建和更新模型对象,应将其视为基本序列化程序定义的扩展。