Django REST Framework: повышение ошибки при добавлении дополнительных полей в POST
Когда вы пишете сериализатор, тривиально указывать, какие поля будут включены (через Meta
fields
), устанавливая права на чтение и запись на них и проверяя их. Тем не менее, мне было интересно узнать, есть ли простой способ указать, что только ожидаемые ожидаемые поля и любые дополнительные ключи должны были вызывать ошибку.
например. скажем, у меня есть сериализатор
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = models.ModelA
fields = ('name', 'number')
Предположим далее, что у меня нет никаких проверок.
И я POST
загружаю эту полезную нагрузку для создания нового экземпляра
{
"name": "test",
"number": 5
}
Все в порядке.
Но предположим, что мой API изменился, и теперь я также сохраняю новое поле title
, но забудьте обновить свой сериализатор. Клиенты будут отправлять полезную нагрузку, которая выглядит как
{
"name": "test",
"number": 5,
"title": "Mr"
}
Однако сериализатор просто игнорирует дополнительный ключ, не создавая исключение.
Итак, мой вопрос: есть ли способ заставить сериализатор ожидать только поля, указанные в fields
или - если это не теги ModelSerializer
-, указанные как члены, и вызывать ошибку, если это не случай?
Ответы
Ответ 1
Наткнулся на этот вопрос и обнаружил, что с помощью проверки уровня объекта немного проще. Это влечет за собой простое определение метода проверки:
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
Вы можете сделать это, переопределив метод is_valid()
для сериализатора. Здесь мы проверим, не является ли какой-либо ключ в payload
не полеми сериализатора с использованием функций filter()
и lambda
.
Если 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)