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

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

问题描述

情境

在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:


  1. 我有一个端点创建一个用户。因此,有一个密码字段和一个 confirm_password 字段。如果两个字段不匹配,则无法创建用户。同样,如果请求的用户名已经存在,则无法创建用户。

  2. 用户POST提供的每个字段的值不正确以上

  3. 在序列化程序(见下文)中已经执行了 validate 的实现,捕获不匹配的密码 confirm_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

验证

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.

验证以特定的无凭证顺序运行


  1. 字段反序列化( serializer.to_internal_value field.run_validators

  2. serializer.validate_ [field] 被调用每个字段

  3. 序列化级别验证器被调用( serializer.run_validation 后跟 serializer.run_validators

  4. serializer
  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

所以你看到的问题是,在序列化程序级验证之前调用级别验证。虽然我不推荐它,您可以通过在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屋!

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