Django REST Framework (DRF) Router 注册流程详解 - 实践
2025-09-29 19:32 tlnshuju 阅读(20) 评论(0) 收藏 举报在使用 Django REST Framework (DRF) 开发 API 的时候,我们常常会看到这样的代码:
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, GroupViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'groups', GroupViewSet)
urlpatterns = router.urls
只需要几行代码,就能自动生成 users/ 和 groups/ 的路由。
那么问题来了:
Router.register() 做了什么?
为什么只需要写 ViewSet 就能生成一堆路由?
router.urls 是怎么来的?
本文将深入解析 DRF Router 的注册流程。
1. Router 的作用
在 Django 原生路由中,我们需要手动写 URL:
urlpatterns = [
path('users/', UserList.as_view()),
path('users//', UserDetail.as_view()),
]
但是在 DRF 中,一个 ViewSet 通常包含了 list/create/retrieve/update/destroy 等多个动作。
如果手写 URL 映射会非常繁琐。
于是,Router 的职责就是:根据 ViewSet 自动生成标准化的 URLConf。
2. Router.register() 做了什么?
以 DefaultRouter 为例,调用 register() 时:
router.register(r'users', UserViewSet)
主要做了三件事:
保存注册信息
把prefix='users'和viewset=UserViewSet存入self.registry列表中。self.registry.append((prefix, viewset, basename))确定 basename
如果没指定,会自动从
UserViewSet.queryset.model推断模型名称(如user)。这个
basename决定了路由命名空间,例如:user-list、user-detail。
延迟生成 URL
register()并不会立刻生成 URL,而是等待访问router.urls时再统一构建。
3. router.urls 是怎么生成的?
当我们访问 router.urls 时,Router 会执行以下流程:
遍历
self.registry中的所有注册项
每个项包含:prefix、viewset、basename调用
get_urls()
根据ViewSet的动作方法(list、create、retrieve、update、partial_update、destroy)生成对应的路由规则。例如
UserViewSet默认生成:URL HTTP方法 动作 /users/GET list /users/POST create /users/{pk}/GET retrieve /users/{pk}/PUT update /users/{pk}/PATCH partial_update /users/{pk}/DELETE destroy 拼接为最终的
urlpatterns
这就是router.urls的来源,最终交给 Django 的 URLConf 系统使用。
4. DefaultRouter 和 SimpleRouter 的区别
SimpleRouter
只生成 CRUD 的基础路由。DefaultRouter
除了 CRUD 路由,还会额外生成一个 根 API 页面(api-root/),列出所有注册的资源入口。
示例:
访问 /api/,会看到:
{
"users": "http://127.0.0.1:8000/api/users/",
"groups": "http://127.0.0.1:8000/api/groups/"
}
5. 自定义 Router
如果你需要定制路由规则,可以继承 SimpleRouter 并重写 routes 属性:
from rest_framework.routers import SimpleRouter, Route
class CustomRouter(SimpleRouter):
routes = [
Route(
url=r'^{prefix}/custom/{lookup}{trailing_slash}$',
mapping={'get': 'custom_action'},
name='{basename}-custom',
detail=True,
initkwargs={'suffix': 'Custom'}
),
]
这样就可以为所有 ViewSet 自动添加一个自定义路由。
6. 总结
register() 负责登记
prefix、viewset、basename,并保存到self.registry。router.urls 在第一次访问时动态生成 URLConf,映射到
ViewSet的标准动作。DefaultRouter 比
SimpleRouter多了一个根 API 入口。Router 本质上就是一个 URL 自动生成器,大大简化了手写路由的工作。
浙公网安备 33010602011771号