Добавление custom_exception_handler

This commit is contained in:
2026-07-18 22:44:06 +03:00
parent 7f87794fcc
commit a8d36b59b4
6 changed files with 93 additions and 4 deletions

View File

@@ -5,7 +5,8 @@
# Все права защищены. Лицензия: MIT # Все права защищены. Лицензия: MIT
""" """
Классов авторизации Пакет классов расширения Django REST Framework
""" """
from .custom_exception_handler import custom_exception_handler
from .expiring_token_authentication import ExpiringTokenAuthentication from .expiring_token_authentication import ExpiringTokenAuthentication

View File

@@ -0,0 +1,87 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание функции custom_exception_handler
"""
from rest_framework import status
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.exceptions import NotAuthenticated
from rest_framework.exceptions import PermissionDenied
from rest_framework.exceptions import ValidationError
from rest_framework.request import Request
from rest_framework.response import Response
from net.xeaf.rack.core import CoreException
from net.xeaf.rack.models.responses import ErrorResponse
from net.xeaf.rack.utils.exceptions import ForbiddenException
from net.xeaf.rack.utils.exceptions import NotFoundException
from net.xeaf.rack.utils.exceptions import UnauthorizedException
def custom_exception_handler(exc: CoreException | Exception, context: dict) -> Response:
"""
Универсальный обработчик исключений
:param exc: Исключение
:param context: Контекст
:return: Ответ
"""
# Получаем информацию о запросе
request = context.get("request")
assert isinstance(request, Request)
# Это наше исключение
if isinstance(exc, CoreException):
return ErrorResponse(status_code=exc.status_code, detail=exc.detail, meta=exc.meta)
# Проверка на стандартное исключение валидации
if isinstance(exc, ValidationError):
return _process_validation_exception(exc)
# Проверка на стандартное исключение авторизации
if isinstance(exc, NotAuthenticated):
return ErrorResponse(status_code=status.HTTP_401_UNAUTHORIZED, detail=UnauthorizedException.Msg.DEFAULT_MESSAGE)
# Проверка на стандартное исключение прав доступа
if isinstance(exc, PermissionDenied):
return ErrorResponse(status_code=status.HTTP_403_FORBIDDEN, detail=ForbiddenException.Msg.DEFAULT_MESSAGE)
# Проверка на стандартное исключение отсутствия реализации
if isinstance(exc, MethodNotAllowed):
return ErrorResponse(status_code=status.HTTP_404_NOT_FOUND, detail=NotFoundException.Msg.DEFAULT_MESSAGE)
# Если ничего другое не прошло
return ErrorResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc))
def _process_validation_exception(exc: ValidationError) -> ErrorResponse:
"""
Обрабатывает частный случай стандартного исключения валидации
:param exc: Исключение
:return: Ответ
"""
if isinstance(exc.detail, list):
if len(exc.detail) == 1:
detail = str(exc.detail[0])
else:
detail = exc.detail
elif isinstance(exc.detail, dict):
detail = {}
for field, error_info in exc.detail.items():
if isinstance(error_info, list):
error = error_info[0]
detail[field] = str(error)
else:
detail = str(exc.detail)
return ErrorResponse(status_code=status.HTTP_400_BAD_REQUEST, detail=detail)

View File

@@ -37,10 +37,10 @@ REST_FRAMEWORK = {
'djangorestframework_camel_case.parser.CamelCaseJSONParser', 'djangorestframework_camel_case.parser.CamelCaseJSONParser',
), ),
'DEFAULT_AUTHENTICATION_CLASSES': [ 'DEFAULT_AUTHENTICATION_CLASSES': [
'net.xeaf.rack.utils.auth.ExpiringTokenAuthentication', 'net.xeaf.rack.utils.drf.ExpiringTokenAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
], ],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10, 'PAGE_SIZE': 10,
# 'EXCEPTION_HANDLER': 'tantal.bdrive.api.utils.custom_exception_handler' 'EXCEPTION_HANDLER': 'net.xeaf.rack.utils.drf.custom_exception_handler'
} }

View File

@@ -11,6 +11,7 @@
from typing import Any from typing import Any
from uuid import UUID from uuid import UUID
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from net.xeaf.rack.core import CoreModel from net.xeaf.rack.core import CoreModel

View File

@@ -21,7 +21,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
SettingUtils.initialize( SettingUtils.initialize(
base_dir=BASE_DIR, base_dir=BASE_DIR,
env_prefix="RACK_", env_prefix="RACK_",
app_name="DRF Rack Demo", app_name="DRF Rack",
url_root="wsgiapp.urls", url_root="wsgiapp.urls",
wsgi_application="wsgiapp.wsgi.application", wsgi_application="wsgiapp.wsgi.application",
) )