Как в Django Rest Framework перенести router.regiter() в декоратор
Написал декоратор который будет регестрировать в переданный router Viewset
def register(router, prefix, basename=None):
def decorator(viewset):
if not prefix:
raise ValueError('Не указано имя Viewset')
if not issubclass(viewset, viewsets.GenericViewSet):
raise ValueError('Wrapped class must subclass GenericViewSet.')
router.register(prefix, viewset, basename)
return viewset
return decorator
Но в urls.py я импортирую роутер в месте инициализации, т.е. app.routers
app.routers.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
Как я понимаю router будет пустой пока файлы с декораторами не будут импортированны в routers.py. Но мне нужно универсальное решение чтобы распространялось на все файлы проекта.
все верно, пока файлы с декораторами не импортированы, router
остаётся пустым.
можно использовать глобальный список для регистраций, например REGISTERED_VIEWSETS
, в который будем временно сохранять ViewSets
.
# app/routers.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
# Глобальный список для отложенной регистрации
REGISTERED_VIEWSETS = []
def register(router, prefix, basename=None):
"""Декоратор для отложенной регистрации ViewSet"""
def decorator(viewset):
if not prefix:
raise ValueError('Не указано имя ViewSet')
if not issubclass(viewset, viewsets.GenericViewSet):
raise ValueError('Wrapped class must subclass GenericViewSet.')
REGISTERED_VIEWSETS.append((prefix, viewset, basename))
return viewset
return decorator
Вместо того, чтобы сразу регистрировать в router
, сначала добавим данные в REGISTERED_VIEWSETS
.
Теперь в urls.py
нужно вызвать регистрацию перед подключением маршрутов
# app/urls.py
from django.urls import path, include
from app.routers import router, REGISTERED_VIEWSETS
for prefix, viewset, basename in REGISTERED_VIEWSETS:
router.register(prefix, viewset, basename)
urlpatterns = [
path('api/', include(router.urls)),
]
Теперь можно применять декоратор к ViewSet
в любом файле без необходимости явно импортировать router
.
from rest_framework import viewsets
from app.routers import register
@register(prefix="users", basename="user")
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer