ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-05-25 21:32:52  阅读:203  来源: 互联网

标签:None code HTTP 自定义 detail rest django 异常 response


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"的响应。

标签:None,code,HTTP,自定义,detail,rest,django,异常,response
来源: https://www.cnblogs.com/rainbow-tan/p/16311001.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有