DRF可浏览API中不显示已引入的应用URL
我明白你遇到的问题了——把路由拆分到各个app的urls.py后,API能正常访问,但DRF的可浏览API根页面就是不显示这些拆分出去的路由,不过drf-spectacular却能正确识别。这其实是DRF可浏览API的一个设计特点,不是bug,咱们一步步来解决。
为什么会出现这个情况? #
DRF的可浏览API根页面是由你在根urls.py里初始化的
DefaultRouter
生成的,这个根路由器只会展示
自己直接注册的ViewSet路由
。而你拆分到
een
app里的是另一个独立的
DefaultRouter
,通过
include
引入后,它的路由属于单独的分支,根路由器根本“不知道”这些路由的存在,自然不会在根页面展示它们。
至于drf-spectacular能识别,是因为它会遍历整个项目的
urlpatterns
来收集API信息,不管路由属于哪个路由器,所以不受这个限制。
解决办法 #
这里有两种常用方案,你可以根据自己的项目需求选择:
方案一:将子app的路由器合并到主路由器(推荐)
这种方法能让根路由器自动包含所有app的路由,可浏览API根页面也会自动展示所有链接,无需手动维护。
修改你的根
urls.py
:
# urls.py from django.contrib import admin from django.urls import include, path from rest_framework.routers import DefaultRouter # 导入子app的路由器 from een.urls import router as een_router import core.views router = DefaultRouter() # 注册core模块的视图集 router.register(r'core/settings', core.views.SettingsViewSet, basename='settings') router.register(r'core/organization', core.views.OrgViewSet, basename='org') # 合并een模块的路由器注册项 router.registry.extend(een_router.registry) urlpatterns = [ path('api/', include(router.urls)), # 移除原来的 path('api/een/', include('een.urls')),因为已经合并了 path('admin/', admin.site.urls), path('', include('rest_framework.urls', namespace='rest_framework')), path('api/tokenauth/', authviews.obtain_auth_token),
这样操作后,主路由器就包含了所有ViewSet的注册信息,访问
/api/
时就能看到所有路由了。
方案二:自定义API根视图(适合完全保持路由拆分的场景)
如果你不想合并路由器,希望每个app的路由完全独立,可以自定义一个根视图,手动列出所有API入口:
修改根
urls.py
:
from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
import core.views
router = DefaultRouter()
router.register(r'core/settings', core.views.SettingsViewSet, basename='settings')
router.register(r'core/organization', core.views.OrgViewSet, basename='org')
# 自定义根视图
@api_view(['GET'])
def api_root(request, format=None):
return Response({
# core模块的路由
'core/settings': reverse('settings-list', request=request, format=format),
'core/organization': reverse('org-list', request=request, format=format),
# een模块的路由,注意要使用app_name的命名空间
'een/cvs': reverse('een:een-cvs-list', request=request, format=format),
# 后续新增路由都需要在这里手动添加
urlpatterns = [
path('api/', api_root), # 把自定义根视图放在最前面
path('api/', include(router.urls)),
path('api/een/', include('een.urls')),