DRF: настройка сообщений об исключениях из API - PullRequest
1 голос
/ 20 февраля 2020

В последнее время я начинаю углубляться в DRF, и мне было интересно, я хотел бы начать настраивать сообщения об ошибках, которые возвращаются через API для неправильных разрешений, я хотел бы обернуть немного больше деталей .

Например, если учетные данные для проверки подлинности не были предоставлены для конечной точки с ограниченным разрешением, API возвращает:

{
    "detail": "Authentication credentials were not provided."
}

, который поступает из строки 171 из rest_framework.exceptions: https://github.com/encode/django-rest-framework/blob/master/rest_framework/exceptions.py. Действительно, я бы хотел, чтобы это соответствовало

{
    "success": false,
    "message": "Authentication credentials were not provided.",
    "data": null
}

Итак, я предполагаю, что теперь мне нужно начать настраивать свои собственные исключения.

Как мне лучше go делать это?

Возможно, в сериализаторе есть некоторые t ie с default_error_messages = {} ...

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Вы можете переопределить обработчик исключений DRF по умолчанию и анализатор JSON на вашем settings.py:

REST_FRAMEWORK = {
    ...
    'EXCEPTION_HANDLER': 'helpers.exceptions.custom_exception_handler',
    'DEFAULT_RENDERER_CLASSES': [
        'helpers.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ]
}

И тогда это всего лишь вопрос настройки того, как обрабатывать ваши исключения и как отображать ответы:

def custom_exception_handler(exc, context):
    # Call REST framework's default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc, context)
    # Customize your exception handling here
    return response

И вы можете использовать пользовательский рендерер JSON на тот случай, если вам нужно будет выполнить дополнительное форматирование ответа, в моем случае мне нужно было добавить «status_code» к полезной нагрузке:

class JSONRenderer(BaseJsonRenderer):
    def render(self, data, accepted_media_type=None, renderer_context=None):
        """
        Render `data` into JSON, returning a bytestring.
        """
        <Base code from the original class...>

        response = renderer_context.get('response')
        if response and 200 <= response.status_code <= 299 and 'status_code' not in response.data:
            response.data = Errors.success(response.data)

        <Base code from the original class...>

Мой Errors.success(response.data) был просто более простым способом объединения кода состояния успеха с данными.

1 голос
/ 20 февраля 2020

Существует решение для декоратора, которое создает пользовательский ответ для каждого типа ваших исключений:

# project/api/exceptions.py
from functools import wraps

from rest_framework import status


def handle_exceptions(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except AuthCredentialsError as exc:
            return Response(
                {"message": exc.message},
                status=status.HTTP_405_METHOD_NOT_ALLOWED,
            )
    return wrapper


# project/api/your_code.py
from project.api.exceptions import handle_exceptions


class SomeViewSet():

    @handle_exceptions
    def create(self, request, *args, **kwargs):
        raise AuthCredentialsError("Authentication credentials were not provided")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...