How can I use multiple routers for a Django Rest Framework project?
I am facing a hard time on trying to use a router for an app and another for another app.
# api/urls.py
from django.urls import path, include
from .views import UserViewSet, DepartmentViewSet, UserLoginView, UserTokenRefreshView
router = DefaultRouter()
router.get_api_root_view().cls.__name__ = "E.R.P. API"
router.get_api_root_view().cls.__doc__ = "API do ERP"
router.register('users', UserViewSet, basename='user')
router.register('departments', DepartmentViewSet, basename='department')
app_name = 'api'
urlpatterns = [
path('login/', UserLoginView.as_view(), name='login'),
path('token/refresh/', UserTokenRefreshView.as_view(), name='token_refresh'),
path('', include(router.urls)),
path('history/', HistoryView.as_view(), name='history'),
]
# mobile_app/urls.py
from django.urls import path, include
from .views import CustomerLoginView
mobile_app_router = DefaultRouter()
mobile_app_router.get_api_root_view().cls.__name__ = "Mobile App API"
mobile_app_router.get_api_root_view().cls.__doc__ = "API do Aplicativo Mobile"
app_name = 'mobile_app'
urlpatterns = [
path('login/', CustomerLoginView.as_view(), name='login'),
path('', include(mobile_app_router.urls))
]
# erp/urls.py
from django.contrib import admin
from django.urls import path, re_path, include
from . import settings
from django.conf.urls.static import static
from notifications import urls as notifications_urls
urlpatterns = [
path('api/', include('api.urls'), name='api'),
path('api/m/', include('mobile_app.urls'), name='api_mobile'),
path('', admin.site.urls),
re_path(r'^inbox/notifications/', include(notifications_urls, namespace='notifications')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
The name and doc are being mixed, if I try to use a swagger or redoc (drf_yasg
) the URLs are mixed. It is like they are the same. How can I do it correctly?
I tried to use multiple routers for a Django Rest Framework and I expect use it as different routers in different urls.
I was able to fix it by implementing the following changes to my code:
# api/urls.py
from django.urls import path, re_path, include
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework.routers import DefaultRouter, APIRootView
from rest_framework import permissions
from accounts.views import UserLoginView, UserTokenRefreshView
from core.views import HistoryView
router = DefaultRouter()
class ErpApiRootView(APIRootView):
"""
API do ERP
"""
router.APIRootView = ErpApiRootView
api_schema_view = get_schema_view(
openapi.Info(
title="ERP API",
default_version='v1',
description="API do ERP",
),
public=True,
permission_classes=(permissions.AllowAny,),
patterns=[path('api/', include('api.urls'))],
)
app_name = 'api'
urlpatterns = [
path('login/', UserLoginView.as_view(), name='login'),
path('token/refresh/', UserTokenRefreshView.as_view(), name='token_refresh'),
path('history/', HistoryView.as_view(), name='history'),
path('', include(router.urls)),
re_path(r'^swagger/$', api_schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
re_path(r'^redoc/$', api_schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
# mobile_app/urls.py
from django.urls import include, path, re_path
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework.routers import DefaultRouter
from rest_framework import permissions
from accounts.views import UserTokenRefreshView
mobile_app_router = DefaultRouter()
class MobileAppAPIRootView(mobile_app_router.APIRootView):
"""
API do App do Cliente
"""
mobile_app_router.APIRootView = MobileAppAPIRootView
mobile_app_schema_view = get_schema_view(
openapi.Info(
title="Mobile App API",
default_version='v1',
description="API do Aplicativo Mobile",
),
public=True,
permission_classes=(permissions.AllowAny,),
patterns=[path('api/m/', include('mobile_app.urls'))],
)
mobile_app_router.register('customers', CustomerViewset, basename='customer')
app_name = 'mobile_app'
urlpatterns = [
path('', include(mobile_app_router.urls)),
re_path(r'^swagger/$', mobile_app_schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui-mobile_app'),
re_path(r'^redoc/$', mobile_app_schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc-mobile_app')
]
The correct way to do this is by instantiating the router and after setting the router's APIRootView as your custom class extending the APIRootView
from rest_framework.routers
. To use the Swagger or Redoc correctly, set the patterns
attribute of get_schema_view()
. The comment inside the class becomes the description at the root of the API.
Some lines have been modified or hidden because the code is private.