Go教程

django-rest-framework学习之路-9-自定义异常以及处理

本文主要是介绍django-rest-framework学习之路-9-自定义异常以及处理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

django-rest-framework学习之路-9-自定义异常以及处理

1、视图默认处理的异常

  • 在REST framework内部产生的APIException 的子类异常。
  • 原生Django的Http404 异常.
  • 原生Django的PermissionDenied 异常.

以上的异常都会被处理,也就是说,如果你写一个异常,然后继承APIException父类,然后通过raise抛出该异常,则这个异常信息就会被处理,当然,django自带的Http404异常以及PermissionDenied通过raise抛出,也是可以正常处理的。

例如:在views.py中直接抛出Http404异常

def create(self, request: Request, *args, **kwargs):
    raise Http404()
    return super().create(request, *args, **kwargs)

image-20220525203006631

如果抛出PermissionDenied异常,则是这样子的

image-20220525203056162

2、自定义异常

  • 需要继承APIException父类

  • 需要在该类中设置.status_code, .default_detail以及default_code属性。

例子:

创建tutorial/custom_exception.py文件且添加代码

from rest_framework.exceptions import APIException
from rest_framework.status import HTTP_400_BAD_REQUEST


class MyException(APIException):
    status_code = HTTP_400_BAD_REQUEST  # 400状态码
    default_detail = '这是自定义异常的default_detail'
    default_code = '这是自定义异常的default_code'

3、自定义异常处理函数

需要写一个函数,接收两个参数,第一个是需要处理的异常,第二个则是一个字典类型。

需要返回一个Response对象或者返回None,返回None则会向上报错,最终返回Django的HTTP 500的server error'响应。

例子

创建一个tutorial/custom_exception_handler.py文件,填充下面的内容

from rest_framework.views import exception_handler


def custom_exception_handler(exc, context):
    # 首先调用REST framework默认的异常处理,
    # 以获得标准的错误响应。
    response = exception_handler(exc, context)
    print(f"type response:{type(response)}")
    print(f"response:{response}")
    print(f"response __dict__:{vars(response)}")

    print(f"type context:{type(context)}")
    print(f"context:{context}")

    # 接下来将HTTP状态码加到响应中。
    if response is not None:
        response.data['status_code'] = response.status_code

    return response

需要在settings.py中配置自定义处理函数

settings.py中配置文件函数路径

REST_FRAMEWORK = {
   ...
    'EXCEPTION_HANDLER': 'tutorial.custom_exception_handler.custom_exception_handler'
}

目录结构

image-20220525210619381

需要raise抛出异常

在snippets/views.py抛出异常

from django.contrib.auth.models import User
from rest_framework import renderers, viewsets, permissions
from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.response import Response

from snippets.models import Snippet
from snippets.permissions import IsOwnerOrReadOnly
from snippets.serializers import SnippetSerializer, UserSerializer
from tutorial.custom_exception import MyException


class UserViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`和`detail`操作。
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer


class SnippetViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`,`create`,`retrieve`,`update`和`destroy`操作。

    另外我们还提供了一个额外的`highlight`操作。
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)

    def perform_create(self, serializer):
        serializer.save()

    def create(self, request: Request, *args, **kwargs):
        raise MyException()
        return super().create(request, *args, **kwargs)

运行

image-20220525210906949

image-20220525211308517

备注:

处理函数的第一个参数是异常,它有下面的属性和方法可以用

exc.detail # 以文字形式返回报错的细节描述。
exc.get_codes() # 返回报错的标识码。
exc.get_full_details() # 返回报错的细节描述以及报错的标识码。

from rest_framework.views import exception_handler


def custom_exception_handler(exc, context):
    # 首先调用REST framework默认的异常处理,
    # 以获得标准的错误响应。
    response = exception_handler(exc, context)

    print(exc.detail)  # 以文字形式返回报错的细节描述。
    print(exc.get_codes())  # 返回报错的标识码。
    print(exc.get_full_details())  # 返回报错的细节描述以及报错的标识码。

    # 接下来将HTTP状态码加到响应中。
    if response is not None:
        response.data['status_code'] = response.status_code

    return response

运行后

image-20220525212047222

4、一些内置的异常

ParseError

签名: ParseError(detail=None, code=None)

在访问request.data时,如果请求中包含格式不正确的数据,则该异常会被抛出。

默认情况下该异常会返回HTTP状态码为"400 Bad Request"的响应。

AuthenticationFailed

签名: AuthenticationFailed(detail=None, code=None)

当请求包含错误的认证信息时抛出。

默认情况下该异常会返回HTTP状态码为"401 Unauthenticated"的响应,但也有可能返回状态码为"403 Forbidden"的响应,这个主要取决于当前使用的认证模式。查看authentication 文档以了解更多细节。

NotAuthenticated

签名: NotAuthenticated(detail=None, code=None)

当未带认证信息的请求检查权限出错时抛出。

默认情况下该异常会返回HTTP状态码为"401 Unauthenticated"的响应,但也有可能返回状态码为"403 Forbidden"的响应,这个主要取决于当前使用的认证模式。查看authentication 文档以了解更多细节。

PermissionDenied

签名: PermissionDenied(detail=None, code=None)

Raised when an authenticated request fails the permission checks.

当一个带认证信息的请求检查权限出错时抛出。

默认情况下该异常会返回HTTP状态码为"403 Forbidden"的响应。

NotFound

签名: NotFound(detail=None, code=None)

当给定URL的资源不存在的时候抛出。这个异常和Django标准的Http404异常等同。

默认情况下该异常会返回HTTP状态码为"404 Not Found"的响应。

MethodNotAllowed

签名: MethodNotAllowed(method, detail=None, code=None)

当一个请求产生且没有view映射了该请求需要的对应方法来处理时抛出。

默认情况下该异常会返回HTTP状态码为"405 Method Not Allowed"的响应。

NotAcceptable

签名: NotAcceptable(detail=None, code=None)

当一个带有Accept头的请求无法被任何当前可用的renderer满足时抛出。

默认情况下该异常会返回HTTP状态码为"406 Not Acceptable"的响应。

UnsupportedMediaType

签名: UnsupportedMediaType(media_type, detail=None, code=None)

当没有解析器能够在访问request.data时处理其content type时抛出。

默认情况下该异常会返回HTTP状态码为"415 Unsupported Media Type"的响应。

Throttled

签名: Throttled(wait=None, detail=None, code=None)

当访问的请求无法通过throttling检查时抛出。

默认情况下该异常会返回HTTP状态码为"429 Too Many Requests"的响应。

这篇关于django-rest-framework学习之路-9-自定义异常以及处理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!