nma*_*rko 26 python django validation django-rest-framework
情况
在Django REST框架中使用验证时ModelSerializer
,我注意到这些Meta.model
字段总是经过验证,即使这样做不一定有意义.以下示例为User
模型的序列化:
password
领域和一个confirm_password
领域.如果两个字段不匹配,则无法创建用户.同样,如果请求username
已存在,则无法创建用户.validate
在串行的情况下(见下文),捕不匹配password
和confirm_password
领域执行validate
:
def validate(self, data):
if data['password'] != data.pop('confirm_password'):
raise serializers.ValidationError("Passwords do not match")
return data
Run Code Online (Sandbox Code Playgroud)
问题
即使ValidationError
被引发validate
,ModelSerializer
仍然会查询数据库以检查它username
是否已被使用.这在从端点返回的错误列表中很明显; 存在模型和非字段错误.
因此,我想知道如何在非字段验证完成之前阻止模型验证,从而节省了对数据库的调用.
尝试解决方案
我一直试图通过DRF的来源找出这种情况发生的地方,但是我找不到我需要覆盖的内容以使其工作失败.
Kev*_*own 66
由于您的username
字段很可能已unique=True
设置,因此Django REST Framework会自动添加一个验证程序,该验证程序会检查以确保新用户名是唯一的.您可以通过执行实际确认repr(serializer())
,这将显示所有自动生成的字段,其中包括验证器.
验证以特定的未记录顺序运行
serializer.to_internal_value
和field.run_validators
)serializer.validate_[field]
为每个字段调用serializer.run_validation
后跟serializer.run_validators
)serializer.validate
叫做因此,您看到的问题是在序列化程序级别验证之前调用字段级验证.虽然我不推荐它,但你可以通过extra_kwargs
在serilalizer的meta中设置来删除字段级验证器.
class Meta:
extra_kwargs = {
"username": {
"validators": [],
},
}
Run Code Online (Sandbox Code Playgroud)
您需要unique
在自己的验证中重新执行检查,以及自动生成的任何其他验证器.
小智 20
我还试图了解在序列化程序验证期间控制如何流动,在仔细阅读 djangorestframework-3.10.3 的源代码后,我想出了以下请求流程图。我已经尽我所能地描述了流程和流程中发生的事情,但没有详细说明,因为它可以从源代码中查找。
忽略不完整的方法签名。只关注在哪些类上调用了哪些方法。
假设当您调用以下代码时is_valid
,您的序列化程序类 ( MySerializer(serializers.Serializer)
)上有一个被覆盖的方法my_serializer.is_valid()
。
MySerializer.is_valid()
被执行。BaseSerializer
)is_valid
方法(例如:super(MySerializer, self).is_valid(raise_exception)
在您的MySerializer.is_valid()
方法中,它将被调用。MySerializer
正在扩展serializers.Serializer
,所以调用了run_validation()
方法 from serializer.Serializers
。这仅验证第一个数据字典。所以我们还没有开始字段级验证。validate_empty_values
from fields.Field
。这再次发生在整个data
领域而不是单个领域。Serializer.to_internal_method
被调用。field.run_validation()
方法。如果该字段已覆盖该Field.run_validation()
方法,则将首先调用该方法。在 a 的情况下,CharField
它被覆盖并调用基类的run_validation
方法Field
。图中步骤6-2。Field.validate_empty_values()
to_internal_value
字段的类型被称为未来。Field.run_validators()
方法的调用。我认为这是我们通过指定validators = []
字段选项在字段上添加的其他验证器一一执行的地方Serializer.to_internal_value()
方法。现在请记住,我们正在为 for 循环中的每个字段执行上述操作。现在,您在序列化程序中编写的自定义字段验证器(如 方法validate_field_name
)已运行。如果在前面的任何步骤中发生异常,您的自定义验证器将不会运行。read_only_defaults()
validate()
您的对象上的方法在这里运行。 归档时间: |
|
查看次数: |
13467 次 |
最近记录: |