Django REST框架中序列化器验证的顺序 [英] Order of Serializer Validation in Django REST Framework
问题描述
情境
在Django REST Framework的 ModelSerializer
我注意到, Meta.model
字段始终被验证,即使这样做并不一定。以用户
模型的序列化为例:
While working with validation in the Django REST Framework's ModelSerializer
, I have noticed that the Meta.model
fields are always validated, even when it does not necessarily make sense to do so. Take the following example for a User
model's serialization:
- 我有一个端点创建一个用户。因此,有一个
密码
字段和一个confirm_password
字段。如果两个字段不匹配,则无法创建用户。同样,如果请求的用户名
已经存在,则无法创建用户。 - 用户POST提供的每个字段的值不正确以上
- 在序列化程序(见下文)中已经执行了
validate
的实现,捕获不匹配的密码
和confirm_password
字段
- I have an endpoint that creates a user. As such, there is a
password
field and aconfirm_password
field. If the two fields do not match, the user cannot be created. Likewise, if the requestedusername
already exists, the user cannot be created. - The user POSTs improper values for each of the fields mentioned above
- An implementation of
validate
has been made in the serializer (see below), catching the non-matchingpassword
andconfirm_password
fields
验证
:
def validate(self, data):
if data['password'] != data.pop('confirm_password'):
raise serializers.ValidationError("Passwords do not match")
return data
问题
即使 ValidationError
由验证
引发, ModelSerializer
仍然查询数据库以检查看看用户名
是否已经在使用。这在从端点返回的错误列表中很明显;存在模型和非字段错误。
Even when the ValidationError
is raised by validate
, the ModelSerializer
still queries the database to check to see if the username
is already in use. This is evident in the error-list that gets returned from the endpoint; both the model and non-field errors are present.
因此,我想知道如何防止模型验证,直到非现场验证完成后,保存我调用我的数据库。
Consequently, I would like to know how to prevent model validation until after non-field validation has finished, saving me a call to my database.
尝试解决方案
Attempt at solution
我一直在试图通过DRF的来源来确定这是发生了什么,但是我没有成功找到我需要覆盖的东西才能使其工作。
I have been trying to go through the DRF's source to figure out where this is happening, but I have been unsuccessful in locating what I need to override in order to get this to work.
推荐答案
由于很可能您的用户名
字段具有 unique = True
设置,Django REST Framework自动添加一个验证器,检查以确保新的用户名是唯一的。您可以通过执行 repr(serializer())
来确认,这将显示所有自动生成的字段,其中包括验证器。
Since most likely your username
field has unique=True
set, Django REST Framework automatically adds a validator that checks to make sure the new username is unique. You can actually confirm this by doing repr(serializer())
, which will show you all of the automatically generated fields, which includes the validators.
验证以特定的无凭证顺序运行
- 字段反序列化(
serializer.to_internal_value
和field.run_validators
) -
serializer.validate_ [field]
被调用每个字段 - 序列化级别验证器被调用(
serializer.run_validation
后跟serializer.run_validators
) -
serializer $>
- Field deserialization called (
serializer.to_internal_value
andfield.run_validators
) serializer.validate_[field]
is called for each field- Serializer-level validators are called (
serializer.run_validation
followed byserializer.run_validators
) serializer.validate
is called
所以你看到的问题是,在序列化程序级验证之前调用级别验证。虽然我不推荐它,您可以通过在serilalizer的元数据中设置 extra_kwargs
来删除字段级验证器。
So the problem that you are seeing is that the field-level validation is called before your serializer-level validation. While I wouldn't recommend it, you can remove the field-level validator by setting extra_kwargs
in your serilalizer's meta.
class Meta:
extra_kwargs = {
"username": {
"validators": [],
},
}
您将需要重新实现唯一的
检查您自己的验证,以及自动生成的任何其他验证器。
You will need to re-implement the unique
check in your own validation though, along with any additional validators that have been automatically generated.
这篇关于Django REST框架中序列化器验证的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!