Django REST Framework:当 POST 上存在额外字段时引发错误

Posted

技术标签:

【中文标题】Django REST Framework:当 POST 上存在额外字段时引发错误【英文标题】:Django REST Framework: raise error when extra fields are present on POST 【发布时间】:2014-04-06 08:39:24 【问题描述】:

在编写序列化程序时,指定将包含哪些字段(通过Metafields)、设置它们的读/写权限并验证它们是很简单的。但是,我想知道是否有一种简单的方法可以指定包含的字段是预期的,并且传入的任何额外键都应该引发错误。

例如比如说,我有一个序列化器

class ModelASerializer(serializers.ModelSerializer):

    class Meta:
        model = models.ModelA
        fields = ('name', 'number')

进一步假设我没有任何验证。

我正在POSTing 这个有效载荷来创建一个新实例


    "name": "test",
    "number": 5

一切都很好。

但假设我的 API 已更改,现在我还存储了一个新字段 title,但忘记更新我的序列化程序。客户端将发送看起来像

的有效载荷

    "name": "test",
    "number": 5,
    "title": "Mr"

然而,序列化程序会简单地忽略额外的键,而不是引发异常。

所以,我的问题是:有没有办法让序列化程序期待fields 中指定的字段,或者——如果不是ModelSerializer——字段,指定为成员,如果不是这种情况,则引发错误?

【问题讨论】:

你可以简单地覆盖restore_objectrestore_fields,打电话给你的父母并检查提供的attrs 稍后再看这个问题,我可能会建议使用jsonschema,如果有效负载未通过架构验证,则会出错。 这能回答你的问题吗? How to make a rest_framework Serializer disallow superfluous fields? 【参考方案1】:

遇到了这个问题,发现使用object level validation 更容易一些。这需要简单地定义一个验证方法:

class ModelASerializer(serializers.ModelSerializer):
    ...
    def validate(self, data):
        if hasattr(self, 'initial_data'):
            unknown_keys = set(self.initial_data.keys()) - set(self.fields.keys())
            if unknown_keys:
                raise ValidationError("Got unknown fields: ".format(unknown_keys))
        return data

【讨论】:

raise ValidationError(unknown_keys.pop(): 'Unexpected field') 也是一个选项。 从 djangorestframework==3.9.4 开始,这似乎不起作用 @SimonKohlmeyer 我不确定您的确切问题,但我遇到了上述检查的错误。所以我更新了答案以包括检查if hasattr(self, 'initial_data'):,因为有时在设置self.initial_data 之前调用.validate 帮助很大。感谢您的回答。 @m【参考方案2】:

您可以通过覆盖序列化程序的is_valid() 方法来做到这一点。在这里,我们将使用filter()lambda 函数检查payload 中的任何键是否不是序列化器字段。

如果filter() 返回了一些不在序列化器字段中的字段,那么我们将引发ValidationError。否则,我们调用super() 方法,然后它将执行正常的序列化程序验证。

from django.core.exceptions import ValidationError

class MySerializer(..):

    def is_valid(self, raise_exception=False):
        if hasattr(self, 'initial_data'):
            payload_keys = self.initial_data.keys() # all the payload keys
            serializer_fields = self.fields.keys() # all the serializer fields
            extra_fields = filter(lambda key: key not in serializer_fields , payload_keys) 
            if extra_fields:
                raise ValidationError('Extra fields %s in payload'%extra_fields)
        return super(MySerializer, self).is_valid(raise_exception)

【讨论】:

以上是关于Django REST Framework:当 POST 上存在额外字段时引发错误的主要内容,如果未能解决你的问题,请参考以下文章

Django REST Framework:当 POST 上存在额外字段时引发错误

Django rest framework ---- 权限

python-django rest framework框架之路由

如何通过 Django Rest Framework 返回嵌套的 json

Django REST Framework 缓存错误

django-rest-framework:每个 ViewSet 可以有多个模板吗?