Django Rest framework: установить ошибку уровня поля из метода serializer validate ()

у меня есть сериализатор, который проверяет поля на основе значений других полей, в ответе на ошибку я хотел бы показать каждую ошибку поля как ошибку поля, а не показывать все в разделе "non_field_errors", что произошло бы, если бы я поднял ValidationError в методе проверки уровня объекта. Ниже приведена иллюстрация того, чего я пытаюсь достичь:

MySerializer(ModelSerializer):
    ...
    def validate(self, data):
        field_val1 = data['field_val1']
        field_val2 = data['field_val2']
        if not self._is_field_valid(field_val1, field_val2):
            # The below line is how I would do what I want with Django
            # Forms, however, it's not valid in DRF
            self._errors['field_val1'] = 'this field is not valid'

желаемый ответ на ошибку:

{'field_val1': ['this field is not valid']}

3 ответов


Я понял это, на этой страница документации в разделе "BaseSerializer", есть пример, который показывает, что ValidationError может принять аргумент словаря при инициализации.

Если Я raise ValidationError({'field_val1': ['this field is not valid']}) Я получаю ответ JSON, который я хочу.


аналогично ответу @Jkk.Джона, это вызывает ValidationError, но он повторно использует исходный текст исключения без необходимости повторной реализации переводов:

try:
    serializer.fields['field_val1'].fail('required')
except ValidationError as exc:
    raise ValidationError({
        'field_val1': exc.detail,
    })

по умолчанию (т. е. on rest_framework.fields.Field class), доступные ключи:

default_error_messages = {
    'required': _('This field is required.'),
    'null': _('This field may not be null.')
}

подклассы могут добавлять свои собственные сообщения об ошибках (и Serializer является наследником Field).

кстати, новые сообщения об ошибках будут автоматически объединены с существующими (унаследованные) сообщения-не будет как и следовало ожидать.


Если у вас есть логика, которая применяется ко всем полям, вы можете все еще получить желаемый результат, делая это:

def validate(self, data):
    for key, value in data.items():
        # checks if value is empty
        if not value:
            raise serializers.ValidationError({key: "This field should not be left empty."})

    return data