Django REST Framework 中序列化程序验证的顺序 [英] Order of Serializer Validation in Django REST Framework

查看:22
本文介绍了Django REST Framework 中序列化程序验证的顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况

在 Django REST Framework 的 ModelSerializer 中使用验证时,我注意到 Meta.model 字段总是经过验证,即使它不一定有意义这样做.以User 模型的序列化为例:

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:

  1. 我有一个创建用户的端点.因此,有一个 password 字段和一个 confirm_password 字段.如果两个字段不匹配,则无法创建用户.同样,如果请求的 username 已经存在,则无法创建用户.
  2. 用户为上述每个字段发布了不正确的值
  3. 在序列化程序中实现了 validate(见下文),捕获不匹配的 passwordconfirm_password 字段
  1. I have an endpoint that creates a user. As such, there is a password field and a confirm_password field. If the two fields do not match, the user cannot be created. Likewise, if the requested username already exists, the user cannot be created.
  2. The user POSTs improper values for each of the fields mentioned above
  3. An implementation of validate has been made in the serializer (see below), catching the non-matching password and confirm_password fields

validate 的实现:

def validate(self, data):
    if data['password'] != data.pop('confirm_password'):
        raise serializers.ValidationError("Passwords do not match")
    return data

问题

即使 ValidationErrorvalidate 引发,ModelSerializer 仍会查询数据库以检查 username 已在使用中.这在从端点返回的错误列表中很明显;模型误差和非现场误差都存在.

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.

尝试解决

我一直试图通过 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.

推荐答案

因为很可能你的 username 字段设置了 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.

验证以特定的、未记录的顺序运行

  1. 字段反序列化调用 (field.run_validators)
  2. serializer][ 为每个字段调用
  3. 调用序列化程序级验证器 ( 后跟 serializer)
  4. serializer.validate> 被称为
  1. Field deserialization called (serializer.to_internal_value and field.run_validators)
  2. serializer.validate_[field] is called for each field
  3. Serializer-level validators are called (serializer.run_validation followed by serializer.run_validators)
  4. serializer.validate is called

因此,您看到的问题是在序列化程序级验证之前调用了字段级验证.虽然我不推荐它,但您可以通过在序列化器的元数据中设置 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": [],
        },
    }

不过,您需要在自己的验证中重新实现 unique 检查,以及自动生成的任何其他验证器.

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 Framework 中序列化程序验证的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆