Добавлен класс CoreViewSet и тесты к нему

This commit is contained in:
2026-07-16 11:52:51 +03:00
parent 4ce8a1ba58
commit b713a2124b
32 changed files with 2263 additions and 55 deletions

View File

@@ -16,4 +16,3 @@ from .core_model import CoreModel
from .core_persistent_model import CorePersistentModel
from .core_persistent_model import CorePersistentModel
from .core_response import CoreResponse
from .core_test_case import CoreTestCase

View File

@@ -1,25 +0,0 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса CoreTestCase
"""
from django.core.management import call_command
from django.test import TestCase
class CoreTestCase(TestCase):
"""
Реализует инициализацию тестовой базы данных перед каждым тестом
"""
def setUp(self):
"""
Подготовка к тестированию
"""
call_command("rack_test_database")

View File

@@ -0,0 +1,11 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Пакет базовых классов для реализации тестов
"""
from .core_test_case import CoreTestCase

View File

@@ -0,0 +1,175 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса CoreTestCase
"""
import json
from django.core.management import call_command
from django.test import TestCase
from rest_framework.parsers import JSONParser
from rest_framework.request import Request
from rest_framework.test import APIRequestFactory
from net.xeaf.rack.management.userstory import AccountTestData
from net.xeaf.rack.management.userstory import SessionTestData
from net.xeaf.rack.models import AccountModel
from net.xeaf.rack.models import SessionModel
class CoreTestCase(TestCase):
"""
Реализует инициализацию тестовой базы данных перед каждым тестом
"""
factory: APIRequestFactory
""" Фабрика запросов """
def setUp(self):
"""
Подготовка к тестированию
"""
call_command("rack_test_database")
self.factory = APIRequestFactory()
def create_request(self, method, path, data=None, query_params=None, auth=None):
"""
Создает DRF Request объект для тестирования
:param method: HTTP метод (GET, POST, PUT, PATCH, DELETE)
:param path: URL путь
:param data: Данные для тела запроса
:param query_params: Параметры запроса
:param auth: Объект аутентификации (сессия)
:return: DRF Request объект
"""
method = method.upper()
data = data or {}
query_params = query_params or {}
# Создаем WSGI request в зависимости от метода
if method == 'GET':
wsgi_request = self.factory.get(path, data=query_params)
elif method == 'POST':
wsgi_request = self.factory.post(path, data=data, format='json')
elif method == 'PUT':
wsgi_request = self.factory.put(path, data=data, format='json')
elif method == 'PATCH':
wsgi_request = self.factory.patch(path, data=data, format='json')
elif method == 'DELETE':
wsgi_request = self.factory.delete(path, data=data, format='json')
else:
wsgi_request = self.factory.generic(
method,
path,
content_type='application/json',
data=json.dumps(data) if data else ''
)
# Преобразуем в DRF Request
drf_request = Request(wsgi_request, parsers=[JSONParser()])
# Добавляем аутентификацию если передана
if auth:
drf_request.auth = auth
if hasattr(auth, 'account'):
drf_request.user = auth.account
# Добавляем query_params для не-GET запросов
if query_params and method != 'GET':
# noinspection PyTypeChecker
drf_request.query_params._mutable = True
for key, value in query_params.items():
drf_request.query_params[key] = value
drf_request.query_params._mutable = False
return drf_request
def create_authenticated_request(self, method, path, token, data=None, query_params=None):
"""
Создает аутентифицированный DRF Request
:param method: HTTP метод
:param path: URL путь
:param token: Токен сессии
:param data: Данные для тела запроса
:param query_params: Параметры запроса
:return: DRF Request с аутентификацией
"""
session = SessionModel.objects.get(token=token)
return self.create_request(method, path, data, query_params, auth=session)
@classmethod
def get_i_ivanov_account(cls) -> AccountModel:
"""
Возвращает аккаунт Ивана И. Иванова
:return: Аккаунт Ивана И. Иванова
"""
return AccountTestData.get_i_ivanov_account()
@classmethod
def get_i_ivanov_session(cls) -> SessionModel:
"""
Возвращает сессию Ивана И. Иванова
:return: Сессия Ивана И. Иванова
"""
return SessionTestData.get_i_ivanov_session()
def create_i_ivanov_request(self, method, path, data=None, query_params=None):
"""
Создает запрос от имени Ивана И. Иванова
"""
return self.create_authenticated_request(
method,
path,
SessionTestData.I_IVANOV_SESSION_TOKEN,
data,
query_params
)
@classmethod
def get_p_petrov_account(cls) -> AccountModel:
"""
Возвращает аккаунт Петра П. Петрова
:return: Аккаунт Петра П. Петрова
"""
return AccountTestData.get_p_petrov_account()
@classmethod
def get_p_petrov_session(cls) -> SessionModel:
"""
Возвращает сессию Петра П. Петрова
:return: Сессия Петра П. Петрова
"""
return SessionTestData.get_p_petrov_session()
def create_p_petrov_request(self, method, path, data=None, query_params=None):
"""
Создает запрос от имени Петра П. Петрова
"""
return self.create_authenticated_request(
method,
path,
SessionTestData.P_PETROV_SESSION_TOKEN,
data,
query_params
)

View File

@@ -0,0 +1,16 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Пакет базовых классов представлений
"""
from .core_view_set import CoreViewSet
from .view_set_create_mixin import ViewSetCreateMixin
from .view_set_destroy_mixin import ViewSetDestroyMixin
from .view_set_list_mixin import ViewSetListMixin
from .view_set_retrieve_mixin import ViewSetRetrieveMixin
from .view_set_update_mixin import ViewSetUpdateMixin

View File

@@ -0,0 +1,283 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса CoreViewSet
"""
from typing import Any
from typing import Type
from uuid import UUID
from django.core.exceptions import ImproperlyConfigured
from django.urls import path
from django.urls import URLPattern
from rest_framework.permissions import IsAuthenticated
from rest_framework.serializers import Serializer
from rest_framework.viewsets import ViewSet
from net.xeaf.rack.enums import HttpMethod
from net.xeaf.rack.enums import ViewSetAction
from net.xeaf.rack.models import AccountModel
from net.xeaf.rack.models import SessionModel
from net.xeaf.rack.utils.exceptions import BadRequestException
from net.xeaf.rack.utils.exceptions import UnauthorizedException
class CoreViewSet(ViewSet):
"""
Реализует базовый функционал для наборов представлений API
"""
permission_classes = (IsAuthenticated,)
""" Классы проверки прав доступа """
item_list_pattern: str | None = None
""" Путь для работы со списком объектов """
item_detail_pattern: str | None = None
""" Путь для работы с объектом """
response_serializer: Type[Serializer] | None = None
""" Общий класс сериализатора для ответа """
def _get_serializer(self, serializer_class: Type[Serializer] | None, default: Type[Serializer] | None) -> Type[Serializer]:
"""
Возвращает класс сериализатора
:param serializer_class: Класс сериализатора
:param default: Класс сериализатора по умолчанию
:return: Класс сериализатора
"""
if serializer_class is not None:
return serializer_class
if default is not None:
return default
raise AttributeError(f"{self.__class__.__name__} must define 'serializer' attribute")
@classmethod
def _process_pk_param(cls, **kwargs: Any) -> UUID | None:
"""
Обработка параметра идентификатора объекта
:param kwargs: Именованные параметры
:return: Идентификатор объекта или None
"""
result = kwargs.get("pk", None)
if not result:
raise BadRequestException()
return UUID(str(result))
def _process_query_params(self, serializer: Type[Serializer] | None, **kwargs: Any) -> dict[str, Any]:
"""
Обрабатывает параметры запроса
:param serializer: Сериализатор параметров
:param kwargs: Именованные аргументы
:return: Параметры запроса
"""
# Строим набор параметров
result = {}
params = list(self.request.query_params)
for param in params:
if param != 'request':
result[param] = self.request.query_params.get(param)
# Добавляем именованные параметры
result.update(kwargs)
# Если был задан сериализатор для параметров
if serializer is not None:
srz = serializer(data=self.request.query_params, context=self._get_request_context())
srz.is_valid(raise_exception=True)
return srz.validated_data
return result
def _process_data_params(self, serializer: Type[Serializer] | None) -> dict[str, Any]:
"""
Обрабатывает параметры данных запроса
:param serializer: Сериализатор параметров
:return: Параметры запроса
"""
data = self.request.data
# Если был задан сериализатор для параметров
if serializer is not None:
partial = self._is_partial_update()
srz = serializer(data=data, context=self._get_request_context(), partial=partial)
srz.is_valid(raise_exception=True)
return srz.validated_data
return data
def _is_partial_update(self) -> bool:
"""
Проверяет, является ли текущий запрос частичным обновлением
:return: True, если запрос является частичным обновлением
"""
return self._get_request_method() == HttpMethod.PATCH
def _get_request_method(self) -> str:
"""
Возвращает имя метода HTTP протокола запроса
:return: Имя метода HTTP протокола запроса
"""
method = self.request.method
if not method:
raise ImproperlyConfigured()
return method.upper()
def _get_request_session[T: SessionModel](self) -> T | None:
"""
Возвращает сессию, связанную с текущим запросом
:return: Сессия, связанная с текущим запросом
"""
# noinspection PyTypeChecker
session: SessionModel = self.request.auth
return session
def _get_request_account[T: AccountModel](self) -> T:
"""
Возвращает аккаунт, связанный с текущим запросом
:return: Аккаунт, связанный с текущим запросом
"""
session = self._get_request_session()
if session is not None:
# noinspection PyTypeChecker
account: T | None = session.account
if account is not None:
return account
raise UnauthorizedException()
def _get_request_context(self) -> dict[str, Any]:
"""
Возвращает контекст запроса
:return: Объект контекста запроса
"""
try:
account = self._get_request_account()
except UnauthorizedException:
account = None
return {
"account": account,
"request": self.request
}
@classmethod
def get_paths(cls) -> list[URLPattern]:
"""
Возвращает полный список путей набора представлений
:return: Список путей
"""
return cls._item_list_paths() + cls._item_detail_paths()
@classmethod
def _path_method(cls, action: ViewSetAction) -> str:
"""
Возвращает имя метода для реализации действия представления
:param action: Действие
:return: Имя метода
"""
return ViewSetAction.get_method(action)
@classmethod
def _path_method_exists(cls, action: ViewSetAction) -> bool:
"""
Проверяет наличие метода для реализации действия представления
:param action: Действие
:return: True, если метод найден, иначе False
"""
method_name = cls._path_method(action)
if hasattr(cls, method_name):
attr = getattr(cls, method_name)
if callable(attr):
return True
return False
@classmethod
def _item_list_paths(cls) -> list[URLPattern]:
"""
Возвращает список путей для работы со списком объектов
:return: Список путей
"""
if cls.item_list_pattern is None:
return []
args = {}
if cls._path_method_exists(ViewSetAction.LIST):
args["get"] = cls._path_method(ViewSetAction.LIST)
if cls._path_method_exists(ViewSetAction.CREATE):
args["post"] = cls._path_method(ViewSetAction.CREATE)
# Если есть путь, но нет методов
if not args:
raise ImproperlyConfigured("No methods defined for item_list_pattern.")
return [path(cls.item_list_pattern, cls.as_view(args))]
@classmethod
def _item_detail_paths(cls) -> list[URLPattern]:
"""
Возвращает список путей для работы с объектом
:return: Список путей
"""
if cls.item_detail_pattern is None:
return []
args = {}
if cls._path_method_exists(ViewSetAction.RETRIEVE):
args["get"] = cls._path_method(ViewSetAction.RETRIEVE)
if cls._path_method_exists(ViewSetAction.UPDATE):
args["put"] = cls._path_method(ViewSetAction.UPDATE)
if cls._path_method_exists(ViewSetAction.PARTIAL_UPDATE):
args["patch"] = cls._path_method(ViewSetAction.PARTIAL_UPDATE)
if cls._path_method_exists(ViewSetAction.DESTROY):
args["delete"] = cls._path_method(ViewSetAction.DESTROY)
# Если есть путь, но нет методов
if not args:
raise ImproperlyConfigured("No methods defined for item_detail_pattern.")
return [path(cls.item_detail_pattern, cls.as_view(args))]

View File

@@ -0,0 +1,92 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса ViewSetCreateMixin
"""
from typing import Any
from typing import Type
from django.db import transaction
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from net.xeaf.rack.core import CoreModel
from net.xeaf.rack.core import CoreResponse
from net.xeaf.rack.enums import HttpMethod
from net.xeaf.rack.models.responses import DataResponse
from .core_view_set import CoreViewSet
class ViewSetCreateMixin(CoreViewSet):
"""
Реализует базовый функционал для создания объекта
"""
create_param_serializer: Type[Serializer] | None = None
""" Класс сериализатора для параметров запроса на создание объекта """
create_data_serializer: Type[Serializer] | None = None
""" Класс сериализатора для данных запроса на создание объекта """
create_response_serializer: Type[Serializer] | None = None
""" Класс сериализатора для ответа на запрос о создании объекта """
def item_create(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ с новым объектом
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
params = self._process_create_params(**kwargs)
with transaction.atomic():
result = self._process_create(params)
return self._process_create_response(result)
def _process_create(self, params: dict[str, Any]) -> dict[str, Any] | CoreModel:
"""
Обрабатывает создание объекта для формирования ответа
:param params: Параметры запроса
:return: Выбранный объект
"""
raise MethodNotAllowed(method=HttpMethod.POST)
def _process_create_params(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
"""
Разбирает и проверяет параметры запроса списка объектов
:param kwargs: Именованные аргументы
:return: Список параметров
"""
query_params = self._process_query_params(self.create_param_serializer, **kwargs)
data_params = self._process_data_params(self.create_data_serializer)
return {**query_params, **data_params}
def _process_create_response(self, data: dict[str, Any] | CoreModel) -> CoreResponse:
"""
Обрабатывает список объектов для формирования ответа
:param data: Список объектов
:return: Ответ для отправки
"""
srz_class = self._get_serializer(self.create_response_serializer, self.response_serializer)
srz = srz_class(data, many=False, context=self._get_request_context())
return DataResponse(data=srz.data)

View File

@@ -0,0 +1,95 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса ViewSetDestroyMixin
"""
import uuid
from typing import Any
from typing import Type
from django.db import transaction
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from net.xeaf.rack.core import CoreModel
from net.xeaf.rack.core import CoreResponse
from net.xeaf.rack.enums import HttpMethod
from net.xeaf.rack.models.responses import DataResponse
from net.xeaf.rack.models.responses import EmptyResponse
from .core_view_set import CoreViewSet
class ViewSetDestroyMixin(CoreViewSet):
"""
Реализует базовый функционал представления для удаления объекта
"""
destroy_param_serializer: Type[Serializer] | None = None
""" Класс сериализатора для параметров запроса объекта """
destroy_response_serializer: Type[Serializer] | None = None
""" Класс сериализатора для ответа на запрос объекта """
def item_destroy(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ с объектом
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
pk = self._process_pk_param(**kwargs)
params = self._process_destroy_params(**kwargs)
with transaction.atomic():
result = self._process_destroy(pk, params)
return self._process_destroy_response(result)
def _process_destroy(self, pk: uuid.UUID | None, params: dict[str, Any]) -> dict[str, Any] | CoreModel | None:
"""
Обрабатывает удаление объекта
:param pk: Идентификатор объекта
:param params: Параметры запроса
:return: Выбранный объект
"""
raise MethodNotAllowed(method=HttpMethod.DELETE)
def _process_destroy_params(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
"""
Разбирает и проверяет параметры запроса объекта
:param kwargs: Именованные аргументы
:return: Список параметров
"""
return self._process_query_params(self.destroy_param_serializer, **kwargs)
def _process_destroy_response(self, data: dict[str, Any] | CoreModel | None) -> CoreResponse:
"""
Обрабатывает объект для формирования ответа
:param data: Список объектов
:return: Ответ для отправки
"""
# Частный случай пустого ответа
if data is None:
return EmptyResponse()
srz_class = self._get_serializer(self.destroy_response_serializer, self.response_serializer)
srz = srz_class(data, many=False, context=self._get_request_context())
return DataResponse(data=srz.data)

View File

@@ -0,0 +1,85 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса ViewSetListMixin
"""
from typing import Any
from typing import Type
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from net.xeaf.rack.core import CoreModel
from net.xeaf.rack.core import CoreResponse
from net.xeaf.rack.enums import HttpMethod
from net.xeaf.rack.models.responses import ListResponse
from .core_view_set import CoreViewSet
class ViewSetListMixin(CoreViewSet):
"""
Реализует базовый функционал для выбора списков
"""
list_param_serializer: Type[Serializer] | None = None
""" Класс сериализатора для параметров запроса списка объектов """
list_response_serializer: Type[Serializer] | None = None
""" Класс сериализатора для ответа на запрос списка объектов """
def item_list(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ со списком объектов
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
params = self._process_list_params(**kwargs)
result = self._process_list(params)
return self._process_list_response(result)
def _process_list(self, params: dict[str, Any]) -> list[dict[str, Any] | CoreModel]:
"""
Обрабатывает выбор списка объектов для формирования ответа
:param params: Параметры запроса
:return: Выбранный объект
"""
raise MethodNotAllowed(method=HttpMethod.GET)
def _process_list_params(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
"""
Разбирает и проверяет параметры запроса списка объектов
:param kwargs: Именованные аргументы
:return: Список параметров
"""
return self._process_query_params(self.list_param_serializer, **kwargs)
def _process_list_response(self, data: list[dict[str, Any] | CoreModel]) -> CoreResponse:
"""
Обрабатывает список объектов для формирования ответа
:param data: Список объектов
:return: Ответ для отправки
"""
srz_class = self._get_serializer(self.list_response_serializer, self.response_serializer)
srz = srz_class(data, many=True, context=self._get_request_context())
return ListResponse(data=list(srz.data))

View File

@@ -0,0 +1,88 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса ViewSetUpdateMixin
"""
import uuid
from typing import Any
from typing import Type
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from net.xeaf.rack.core import CoreModel
from net.xeaf.rack.core import CoreResponse
from net.xeaf.rack.enums import HttpMethod
from net.xeaf.rack.models.responses import DataResponse
from .core_view_set import CoreViewSet
class ViewSetRetrieveMixin(CoreViewSet):
"""
Реализует базовый функционал представления для выбора объекта
"""
retrieve_param_serializer: Type[Serializer] | None = None
""" Класс сериализатора для параметров запроса объекта """
retrieve_response_serializer: Type[Serializer] | None = None
""" Класс сериализатора для ответа на запрос объекта """
def item_retrieve(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ с объектом
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
pk = self._process_pk_param(**kwargs)
params = self._process_retrieve_params(**kwargs)
result = self._process_retrieve(pk, params)
return self._process_retrieve_response(result)
def _process_retrieve(self, pk: uuid.UUID | None, params: dict[str, Any]) -> dict[str, Any] | CoreModel:
"""
Обрабатывает выбор объекта для формирования ответа
:param pk: Идентификатор объекта
:param params: Параметры запроса
:return: Выбранный объект
"""
raise MethodNotAllowed(method=HttpMethod.GET)
def _process_retrieve_params(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
"""
Разбирает и проверяет параметры запроса объекта
:param kwargs: Именованные аргументы
:return: Список параметров
"""
return self._process_query_params(self.retrieve_param_serializer, **kwargs)
def _process_retrieve_response(self, data: dict[str, Any] | CoreModel) -> CoreResponse:
"""
Обрабатывает объект для формирования ответа
:param data: Список объектов
:return: Ответ для отправки
"""
srz_class = self._get_serializer(self.retrieve_response_serializer, self.response_serializer)
srz = srz_class(data, many=False, context=self._get_request_context())
return DataResponse(data=srz.data)

View File

@@ -0,0 +1,107 @@
# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса ViewSetUpdateMixin
"""
import uuid
from typing import Any
from typing import Type
from django.db import transaction
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from net.xeaf.rack.core import CoreModel
from net.xeaf.rack.core import CoreResponse
from net.xeaf.rack.models.responses import DataResponse
from .core_view_set import CoreViewSet
class ViewSetUpdateMixin(CoreViewSet):
"""
Реализует базовый функционал представления для изменения объекта
"""
update_param_serializer: Type[Serializer] | None = None
""" Класс сериализатора для параметров запроса на изменение объекта """
update_data_serializer: Type[Serializer] | None = None
""" Класс сериализатора для данных запроса на изменение объекта """
update_response_serializer: Type[Serializer] | None = None
""" Класс сериализатора для ответа на запрос на изменение объекта """
def item_update(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ с объектом
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
pk = self._process_pk_param(**kwargs)
params = self._process_update_params(**kwargs)
with transaction.atomic():
result = self._process_update(pk, params)
return self._process_update_response(result)
def item_partial_update(self, request: Request, **kwargs: dict[str, Any]) -> CoreResponse:
"""
Обрабатывает HTTP запрос и возвращает ответ с измененным объектом
:param request: Запрос
:param kwargs: Именованные аргументы
:return: Ответ
"""
return self.item_update(request, **kwargs)
def _process_update(self, pk: uuid.UUID | None, params: dict[str, Any]) -> dict[str, Any] | CoreModel:
"""
Обрабатывает выбор и изменение объекта для формирования ответа
:param pk: Идентификатор объекта
:param params: Параметры запроса
:return: Выбранный объект
"""
raise MethodNotAllowed(method=self._get_request_method())
def _process_update_params(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
"""
Разбирает и проверяет параметры запроса объекта
:param kwargs: Именованные аргументы
:return: Список параметров
"""
query_params = self._process_query_params(self.update_param_serializer, **kwargs)
data_params = self._process_data_params(self.update_data_serializer)
return {**query_params, **data_params}
def _process_update_response(self, data: dict[str, Any] | CoreModel) -> CoreResponse:
"""
Обрабатывает объект для формирования ответа
:param data: Список объектов
:return: Ответ для отправки
"""
srz_class = self._get_serializer(self.update_response_serializer, self.response_serializer)
srz = srz_class(data, many=False, context=self._get_request_context())
return DataResponse(data=srz.data)