DRF:自定义来自API的异常消息

时间:2020-02-20 09:48:18

标签: django django-rest-framework django-rest-framework-simplejwt

最近我将开始深入研究DRF,我想知道我想开始自定义错误消息,该消息通过API返回以获取不正确的权限,我想包装一些额外的细节

例如,如果未为受权限限制的端点提供身份验证凭据,则API返回:

1

来自{ "detail": "Authentication credentials were not provided." } https://github.com/encode/django-rest-framework/blob/master/rest_framework/exceptions.py的第171行。真的,我希望这与

保持一致
rest_framework.exceptions

因此,我假设我现在需要开始自定义自己的异常。

我应该如何最好地做到这一点?

也许它与序列化程序中的{ "success": false, "message": "Authentication credentials were not provided.", "data": null } 有联系...

2 个答案:

答案 0 :(得分:1)

有一个装饰器解决方案,可以针对每种类型的异常创建自定义响应:

# 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")

答案 1 :(得分:1)

您可以在REST_FRAMEWORK = { ... 'EXCEPTION_HANDLER': 'helpers.exceptions.custom_exception_handler', 'DEFAULT_RENDERER_CLASSES': [ 'helpers.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ] } 上覆盖DRF的默认异常处理程序和JSON解析器:

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

然后只需自定义如何处理异常以及如何呈现响应:

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...>

并且您可以使用自定义JSON渲染器,以防您需要对响应进行任何其他格式化,在我的情况下,我必须向有效负载添加“ status_code”:

Errors.success(response.data)

我的mypath = r"/Users/Anas/Desktop/Parcours Centrale Lille/G3/Projet d'intégration/Toolbox/LibriSpeech_dev_clean_mfcc" for key,vec in kaldi_io.read_vec_flt_scp(mypath): print("mfcc of id ",key,"is equal to ",vec) 只是将成功状态代码合并到数据中的一种简单方法。