如何在Django Rest Framework项目中正确使用多路由?
解决多App配置DefaultRouter时的路由混淆问题
问题根源
你遇到的__name__、__doc__混淆以及Swagger/Redoc URL混乱,本质是因为所有DefaultRouter实例默认共享同一个根视图基类。直接通过router.get_api_root_view().cls.__name__修改属性时,你其实是在修改这个共享基类本身,导致所有router实例都会继承这些修改后的属性,自然会出现混淆。
正确配置方案
不要直接修改共享的根视图类,而是为每个App创建独立的自定义根视图类,让每个Router使用自己的专属根视图,彻底隔离属性。
1. 简洁版实现(仅修改名称和文档)
如果不需要自定义根视图的返回逻辑,直接继承DefaultRouter的默认根视图类,修改专属属性即可:
修改后的 api/urls.py
from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import UserViewSet, DepartmentViewSet, UserLoginView, UserTokenRefreshView, HistoryView # 自定义ERP API根视图类 class ERPApiRootView(DefaultRouter.APIRootView): __name__ = "E.R.P. API" __doc__ = "API do ERP" router = DefaultRouter() # 替换router的根视图为自定义类 router.APIRootView = ERPApiRootView 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 rest_framework.routers import DefaultRouter from .views import CustomerLoginView # 自定义Mobile App根视图类 class MobileApiRootView(DefaultRouter.APIRootView): __name__ = "Mobile App API" __doc__ = "API do Aplicativo Mobile" mobile_app_router = DefaultRouter() # 替换为自定义根视图类 mobile_app_router.APIRootView = MobileApiRootView app_name = 'mobile_app' urlpatterns = [ path('login/', CustomerLoginView.as_view(), name='login'), path('', include(mobile_app_router.urls)) ]
2. 自定义根视图逻辑版(如需修改返回内容)
如果需要自定义根视图的返回结构,可以重写get方法:
from rest_framework.views import APIView from rest_framework.response import Response class ERPApiRootView(APIView): __name__ = "E.R.P. API" __doc__ = "API do ERP" def get(self, request, *args, **kwargs): # 自定义返回的路由链接结构 data = { "users": request.build_absolute_uri("users/"), "departments": request.build_absolute_uri("departments/"), "login": request.build_absolute_uri("login/") } return Response(data)
关键效果
- 每个Router的
APIRootView指向独立类,__name__和__doc__完全隔离,不会互相覆盖 - drf_yasg会正确识别不同路径下的Router实例,Swagger/Redoc中的URL映射不再混乱
- 保留DefaultRouter的原有路由生成逻辑,无需额外改动业务视图
内容的提问来源于stack exchange,提问作者Leonardo Costa
相关产品推荐
相关产品推荐

