Django REST Framework: raise error when extra fields are present on POST

寵の児 提交于 2021-02-17 21:13:32

问题


When you're writing a serializer, it is trivial to specify which fields will be included (via Meta's fields), setting read/write permissions on them and validating them. However, I was wondering if there is an easy way to specify that only the fields that are included are to be expected and any extra keys passed in should raise an error.

E.g. say, I have a serializer

class ModelASerializer(serializers.ModelSerializer):

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

Supposed further that I don't have any validations.

And I'm POSTing this payload to create a new instance

{
    "name": "test",
    "number": 5
}

Everything is fine.

But suppose my API has changed and now I'm also storing a new field, title, but forget to update my serializer. Clients will be sending payloads that look like

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

However the serializer will simply ignore the extra key, not raising an exception.

So, my question is: is there any way to make a serializer only expect fields specified in fields or -- if it's not a ModelSerializer -- fields, specified as members, and raise an error if it's not the case?


回答1:


Came across this question and found that using object level validation is a bit easier. This entails simply defining a validate method:

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



回答2:


You can do that by overriding the is_valid() method of the serializer. Here, we will check if any of the key in the payload is not a serializer field using filter() and lambda functions.

If filter() returns some fields which are not in the serializer fields, then we raise a ValidationError. Else, we call the super() method and it will then perform the normal serializer validation.

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)


来源:https://stackoverflow.com/questions/22178266/django-rest-framework-raise-error-when-extra-fields-are-present-on-post

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!