Django REST Framework 中序列化器验证的顺序

2024-01-11

情况

在 Django REST Framework 中进行验证时ModelSerializer,我注意到Meta.model字段始终经过验证,即使这样做不一定有意义。以下面的例子为例User模型的序列化:

  1. 我有一个创建用户的端点。因此,有一个password场和一个confirm_password场地。如果两个字段不匹配,则无法创建用户。同样,如果要求username已存在,无法创建该用户。
  2. 用户为上述每个字段发布了不正确的值
  3. 一个实现validate已在序列化器中进行(见下文),捕获不匹配的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

Problem

即使当ValidationError是由validate, the ModelSerializer仍然查询数据库来检查是否username已在使用中。这在从端点返回的错误列表中很明显;模型误差和非现场误差都存在。

因此,我想知道如何在非字段验证完成之前阻止模型验证,从而节省对数据库的调用。

尝试解决方案

我一直在尝试查看 DRF 的源代码来找出发生这种情况的位置,但我未能成功找到需要覆盖的内容才能使其正常工作。


因为很可能你的username场有unique=True设置后,Django REST Framework 会自动添加一个验证器来检查以确保新用户名是唯一的。您实际上可以通过执行以下操作来确认这一点repr(serializer()),它将向您显示所有自动生成的字段,其中包括验证器。

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

  1. 字段反序列化称为 (serializer.to_internal_value https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L374 and field.run_validators https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L397)
  2. serializer.validate_[field] https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L399为每个字段调用
  3. 序列化器级别的验证器称为(serializer.run_validation https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L186其次是serializer.run_validators https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L366)
  4. serializer.validate https://github.com/tomchristie/django-rest-framework/blob/e39d8410de26003421f7e644f9206833a3b9bbe0/rest_framework/serializers.py#L367叫做

因此,您看到的问题是在序列化器级验证之前调用字段级验证。虽然我不推荐它,但您可以通过设置来删除字段级验证器extra_kwargs在你的序列化器的元中。

class Meta:
    extra_kwargs = {
        "username": {
            "validators": [],
        },
    }

您将需要重新实施unique不过,请检查您自己的验证以及自动生成的任何其他验证器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django REST Framework 中序列化器验证的顺序 的相关文章

随机推荐