Переписать обработчик ошибок валидации по умолчанию в django rest
Я использую django-rest для своего бэкенда и хочу переписать ошибки по умолчанию для полей. Мой текущий код выглядит следующим образом.
class DeckSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = (
"id",
"title",
"get_absolute_url",
"description",
"price",
"image",
"category_id",
"category",
"title"
)
extra_kwargs = {
'title': {"error_messages": {"required": "Title cannot be empty"}},
'image': {"error_messages": {"required": "Image cannot be empty"},}
}
После написания этих двух kwargs я понял, что просто повторяю то, что можно было бы решить с помощью кода.
По умолчанию валидация сериализатора возвращает это значение, если поле отсутствует {title:"This field is required"}.
Есть ли способ перезаписать текущее сообщение, чтобы оно отображало непосредственно name_of_the_field + my_message. Пример {title: Title is required}
Я не ищу, как написать пользовательское сообщение об ошибке для одного поля, я ищу, как написать общие сообщения об ошибке для каждого поля, которое, например, отсутствует или равно null.
Мы можем достичь этого, написав пользовательский обработчик исключений.
Вот как может выглядеть пользовательский ответ:
{
"status_code": 400,
"type": "ValidationError",
"message": "Bad request syntax or unsupported method",
"errors": [
"username: This field may not be null.",
"email: This field may not be null.",
"ticket number: This field may not be null."
]
}
Нам нужно создать файл: exception_handler.py в каталоге нашего проекта с кодом, который следует за ним; я использую utils для таких целей. Вы также можете поместить этот код куда угодно, но я предпочитаю иметь его в отдельном файле, предназначенном для этой цели.
from http import HTTPStatus
from rest_framework import exceptions
from rest_framework.views import Response, exception_handler
def api_exception_handler(exception: Exception, context: dict) -> Response:
"""Custom API exception handler."""
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exception, context)
# Only alter the response when it's a validation error
if not isinstance(exception, exceptions.ValidationError):
return response
# It's a validation error, there should be a Serializer
view = context.get("view", None)
serializer = view.get_serializer_class()()
errors_list = []
for key, details in response.data.items():
if key in serializer.fields:
label = serializer.fields[key].label
help_text = serializer.fields[key].help_text
for message in details:
errors_list.append("{}: {}".format(label, message))
elif key == "non_field_errors":
for message in details:
errors_list.append(message)
else:
for message in details:
errors_list.append("{}: {}".format(key, message))
# Using the description's of the HTTPStatus class as error message.
http_code_to_message = {v.value: v.description for v in HTTPStatus}
error_payload = {
"status_code": 0,
"type": "ValidationError",
"message": "",
"errors": [],
}
# error = error_payload["error"]
status_code = response.status_code
error_payload["status_code"] = status_code
error_payload["message"] = http_code_to_message[status_code]
error_payload["errors"] = errors_list
# Overwrite default exception_handler response data
response.data = error_payload
return response
Основная идея взята из отсюда, но я изменил ее под свои нужды. измените ее по своему усмотрению.
Не забудьте установить его в качестве обработчика исключений по умолчанию в вашем settings.py файле:
REST_FRAMEWORK["EXCEPTION_HANDLER"] = "utils.exception_handler.api_exception_handler";