Django rest framework ----異常處理 Exceptions


REST framework提供了異常處理,我們可以自定義異常處理函數。

官方文檔

https://www.django-rest-framework.org/api-guide/exceptions/

在配置文件中配置日志

setting.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已經存在的日志器
    'formatters': {  # 日志信息顯示的格式
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {  # 對日志進行過濾
        'require_debug_true': {  # django在debug模式下才輸出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志處理方法
        'console': {  # 向終端中輸出日志
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # 向文件中輸出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(BASE_DIR, "logs/meiduo.log"),  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定義了一個名為django的日志器
            'handlers': ['console', 'file'],  # 可以同時向終端與文件中輸出日志
            'propagate': True,  # 是否繼續傳遞日志信息
            'level': 'INFO',  # 日志器接收的最低日志級別
        },
    }
}

 

 

DRFDemo/utils/exceptions.py

from rest_framework.views import exception_handler
 
def custom_exception_handler(exc, context):
    # 先調用REST framework默認的異常處理方法獲得標准錯誤響應對象
    response = exception_handler(exc, context)
 
    # 在此處補充自定義的異常處理
    if response is not None:
        response.data['status_code'] = response.status_code
 
    return response

在配置文件中聲明自定義的異常處理  

REST_FRAMEWORK = {
  'EXCEPTION_HANDLER': 'DRFDemo.utils.custom_exception_handler'
}

  

如果未聲明,會采用默認的方式,如下

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

例如:

補充上處理關於數據庫的異常

from django.db import DatabaseError
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import exception_handler
 
 
def custom_exception_handler(exc, context):
    # 先調用REST framework默認的異常處理方法獲得標准錯誤響應對象
    response = exception_handler(exc, context)
 
    # 在此處補充自定義的異常處理
    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError):
            print('[%s]: %s' % (view, exc))
            response = Response({'detail': '服務器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
 
    return response 

 

完整代碼如下

from rest_framework.views import exception_handler as drf_exception_handler
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status

# 獲取在配置文件中定義的logger,用來記錄日志
logger = logging.getLogger('django')

def exception_handler(exc, context):
    """
    自定義異常處理
    :param exc: 異常
    :param context: 拋出異常的上下文
    :return: Response響應對象
    """
    # 調用drf框架原生的異常處理方法
    response = drf_exception_handler(exc, context)

    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 數據庫異常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '服務器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

    return response
DRFDemo/utils/exceptions.py

 

 

代碼中模擬一個異常:  

from django.db import DatabaseError
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    # authentication_classes = (SessionAuthentication, BasicAuthentication)
    # permission_classes = (IsAuthenticated,)
    filter_fields = ("btitle", "bread")
    # pagination_class = LargeResultsSetPagination
    pagination_class = LimitOffsetPagination
 
    def get_permissions(self):
        if action == "get":
            return [IsAuthenticated()]
        else:
            return [AllowAny()]
 
    @action(methods=["GET"], detail=False)
    def latest(self, request):
        raise DatabaseError()
        book = BookInfo.objects.latest("id")
        serializer = self.get_serializer(book)
        return Response(serializer.data)

  

訪問:

REST framework定義的異常

APIException 所有異常的父類
ParseError 解析錯誤
AuthenticationFailed 認證失敗
NotAuthenticated 尚未認證
PermissionDenied 權限決絕
NotFound 未找到
MethodNotAllowed 請求方式不支持
NotAcceptable 要獲取的數據格式不支持
Throttled 超過限流次數
ValidationError 校驗失敗

  

自定義一個捕獲數據庫查詢不到的異常

import logging

from django.core.exceptions import ObjectDoesNotExist
from rest_framework.exceptions import NotFound
from rest_framework.views import exception_handler as old_exception_handler

logger = logging.getLogger(__name__)


def exception_handler(exc, context):
    logger.exception('Uncaught Exception')
    if isinstance(exc, ObjectDoesNotExist):
        exc = NotFound()
    return old_exception_handler(
        exc, context
    )

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM