1. DRF 异常处理
Django DRF 异常处理
1. DRF对异常(Exception)的处理源码
request请求先进到APIView的dispatch方法, 如果有异常走到exception。
2. 自定义异常返回
utils/handlers.py
from django.http import Http404
from rest_framework import exceptions
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import Throttled
from rest_framework.exceptions import PermissionDenied
from rest_framework.exceptions import NotAuthenticated
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.views import set_rollback
def exception_handler(exc, context):
if isinstance(exc, Http404):
exc = exceptions.NotFound()
exc.ret_code = 1001
elif isinstance(exc, PermissionDenied):
exc = exceptions.PermissionDenied()
exc.ret_code = 1002
elif isinstance(exc, (AuthenticationFailed, NotAuthenticated)):
exc.ret_code = 1003
elif isinstance(exc, Throttled):
exc.ret_code = 1004
elif isinstance(exc, ValidationError):
exc.ret_code = 1005
# 只处理drf相关的异常
if isinstance(exc, exceptions.APIException):
headers = {}
if getattr(exc, 'auth_header', None):
headers['WWW-Authenticate'] = exc.auth_header
if getattr(exc, 'wait', None):
headers['Retry-After'] = '%d' % exc.wait
if isinstance(exc.detail, (list, dict)):
data = exc.detail
else:
code = getattr(exc, 'ret_code', None) or -1
data = {'code': code, 'detail': exc.detail}
set_rollback()
return Response(data, status=exc.status_code, headers=headers)
return None
utils/exceptions.py
from rest_framework import exceptions
class ExtraException(exceptions.APIException):
def __init__(self, detail=None, ret_code=None, code=None):
super().__init__(detail, code)
self.ret_code = ret_code
views.py
from rest_framework import exceptions
from rest_framework import serializers
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.throttling import BaseThrottle
from api import models
from utils.exceptions import ExtraException
class ExtraAuthentication(BaseAuthentication):
def authenticate(self, request):
raise exceptions.AuthenticationFailed("认证失败")
def authenticate_header(self, request):
return "api"
class ExtraPermission(BasePermission):
def has_permission(self, request, view):
return False
def has_object_permission(self, request, view, obj):
return False
class ExtraThrottle(BaseThrottle):
def allow_request(self, request, view):
return False
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
class DemoView(ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin,
GenericViewSet):
# authentication_classes = [ExtraAuthentication]
# throttle_classes = [ExtraThrottle]
# permission_classes = [ExtraPermission]
queryset = models.UserInfo.objects.all()
serializer_class = DemoSerializer
def perform_create(self, serializer):
self.dispatch
if True:
# 自定义错误
# raise ExtraException("数据异常")
raise ExtraException("更新失败", ret_code=9000)
serializer.save()
def finalize_response(self, request, response, *args, **kwargs):
response = super().finalize_response(request, response, *args, **kwargs)
if response.exception:
return response
response.data = {'code': 0, 'data': response.data}
return response