diff --git a/net/xeaf/rack/models/responses/error_response.py b/net/xeaf/rack/models/responses/error_response.py index bd74c7f..b7c055d 100644 --- a/net/xeaf/rack/models/responses/error_response.py +++ b/net/xeaf/rack/models/responses/error_response.py @@ -18,32 +18,34 @@ class ErrorResponse(CoreResponse): Ответ с информацией об ошибке """ - def __init__(self, status_code: int, detail: list | dict | str | bool | None, meta: dict | None = None): + def __init__(self, status_code: int, detail: list | dict | str | bool | None, meta: dict | None = None, pure_status: bool = False): """ Инициализация :param status_code: Код состояния :param detail: Информация об ошибке :param meta: Дополнительные данные + :param pure_status: Возвращать настоящий код состояния """ super(ErrorResponse, self).__init__( internal_status=status_code, - external_status=self._calc_external_status(status_code), + external_status=self._calc_external_status(status_code, pure_status), data=detail, meta=meta) @classmethod - def _calc_external_status(cls, status_code: int) -> int: + def _calc_external_status(cls, status_code: int, pure_status: bool) -> int: """ Вычисляет значение внешнего возвращаемого статуса :param status_code: Код состояния + :param pure_status: Возвращать настоящий код состояния :return: Внешний код состояния """ - if status_code < status.HTTP_500_INTERNAL_SERVER_ERROR: + if status_code < status.HTTP_500_INTERNAL_SERVER_ERROR and not pure_status: return status.HTTP_200_OK return status_code diff --git a/net/xeaf/rack/utils/drf/custom_exception_handler.py b/net/xeaf/rack/utils/drf/custom_exception_handler.py index 8dfe6d1..66b0ef6 100644 --- a/net/xeaf/rack/utils/drf/custom_exception_handler.py +++ b/net/xeaf/rack/utils/drf/custom_exception_handler.py @@ -39,7 +39,7 @@ def custom_exception_handler(exc: CoreException | Exception, context: dict) -> R # Это наше исключение if isinstance(exc, CoreException): - return ErrorResponse(status_code=exc.status_code, detail=exc.detail, meta=exc.meta) + return ErrorResponse(status_code=exc.status_code, detail=exc.detail, meta=exc.meta, pure_status=exc.is_pure_status()) # Проверка на стандартное исключение валидации if isinstance(exc, ValidationError): diff --git a/net/xeaf/rack/views/__init__.py b/net/xeaf/rack/views/__init__.py index 8dc9854..dc19b3b 100644 --- a/net/xeaf/rack/views/__init__.py +++ b/net/xeaf/rack/views/__init__.py @@ -8,4 +8,5 @@ Пакет описания классов представлений """ +from .error_404_handler_view_set import Error404HandlerViewSet from .version_view_set import VersionViewSet diff --git a/net/xeaf/rack/views/error_404_handler_view_set.py b/net/xeaf/rack/views/error_404_handler_view_set.py new file mode 100644 index 0000000..450f218 --- /dev/null +++ b/net/xeaf/rack/views/error_404_handler_view_set.py @@ -0,0 +1,59 @@ +# DRF Rack +# Библиотека классов расширений для Django REST Framework +# +# Автор: Николай В. Анохин +# Все права защищены. Лицензия: MIT + +""" +Описание класса Error404HandlerViewSet +""" + +from typing import Any + +from django.urls import re_path +from django.urls import URLPattern +from rest_framework.permissions import AllowAny +from rest_framework.request import Request + +from net.xeaf.rack.core.views import CoreViewSet +from net.xeaf.rack.core.views import ViewSetListMixin +from net.xeaf.rack.core.views import ViewSetRetrieveMixin +from net.xeaf.rack.utils.exceptions import FileNotFoundException + + +class Error404HandlerViewSet(ViewSetListMixin, ViewSetRetrieveMixin, CoreViewSet): + """ + Реализует базовый функционал обработчика переходов по несуществующим адресам + """ + + permission_classes = [AllowAny, ] + """ Классы проверки прав доступа """ + + def raise404(self, request: Request, **kwargs: dict[str, Any]): + """ + Выбрасывает исключение 404 + """ + + raise FileNotFoundException() + + @classmethod + def get_path(cls) -> list[URLPattern]: + """ + Возвращает полный список путей набора представлений + + :return: Список путей + """ + + # Аргументы + args = { + "get": "raise404", + "post": "raise404", + "patch": "raise404", + "put": "raise404", + "delete": "raise404" + } + + return [ + re_path(r'^.*/$', cls.as_view(args)), + re_path(r'^.*$', cls.as_view(args)), + ] diff --git a/net/xeaf/rack/views/version_view_set.py b/net/xeaf/rack/views/version_view_set.py index 59eed40..eda8021 100644 --- a/net/xeaf/rack/views/version_view_set.py +++ b/net/xeaf/rack/views/version_view_set.py @@ -11,7 +11,6 @@ from typing import Any from uuid import UUID -from rest_framework.exceptions import ValidationError from rest_framework.permissions import AllowAny from net.xeaf.rack.core import CoreModel diff --git a/wsgiapp/urls.py b/wsgiapp/urls.py index 77611a1..b5e34a6 100644 --- a/wsgiapp/urls.py +++ b/wsgiapp/urls.py @@ -11,9 +11,14 @@ from django.urls import include from django.urls import path +from net.xeaf.rack.views import Error404HandlerViewSet + # # Маршруты # urlpatterns = [ path('v1/', include('net.xeaf.rack.urls')), + + # Должен быть последним + *Error404HandlerViewSet.get_path(), ]