Django REST Framework (DRF) Router 注册流程详解

在使用 Django REST Framework (DRF) 开发 API 的时候,我们常常会看到这样的代码:

python 复制代码
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:

python 复制代码
urlpatterns = [
    path('users/', UserList.as_view()),
    path('users/<int:pk>/', UserDetail.as_view()),
]

但是在 DRF 中,一个 ViewSet 通常包含了 list/create/retrieve/update/destroy 等多个动作。

如果手写 URL 映射会非常繁琐。

于是,Router 的职责就是:根据 ViewSet 自动生成标准化的 URLConf


2. Router.register() 做了什么?

DefaultRouter 为例,调用 register() 时:

python 复制代码
router.register(r'users', UserViewSet)

主要做了三件事:

  1. 保存注册信息

    prefix='users'viewset=UserViewSet 存入 self.registry 列表中。

    python 复制代码
    self.registry.append((prefix, viewset, basename))
  2. 确定 basename

    • 如果没指定,会自动从 UserViewSet.queryset.model 推断模型名称(如 user)。

    • 这个 basename 决定了路由命名空间,例如:user-listuser-detail

  3. 延迟生成 URL
    register() 并不会立刻生成 URL,而是等待访问 router.urls 时再统一构建。


3. router.urls 是怎么生成的?

当我们访问 router.urls 时,Router 会执行以下流程:

  1. 遍历 self.registry 中的所有注册项

    每个项包含:prefixviewsetbasename

  2. 调用 get_urls()

    根据 ViewSet 的动作方法(listcreateretrieveupdatepartial_updatedestroy)生成对应的路由规则。

    例如 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
  3. 拼接为最终的 urlpatterns

    这就是 router.urls 的来源,最终交给 Django 的 URLConf 系统使用。


4. DefaultRouter 和 SimpleRouter 的区别

  • SimpleRouter

    只生成 CRUD 的基础路由。

  • DefaultRouter

    除了 CRUD 路由,还会额外生成一个 根 API 页面api-root/),列出所有注册的资源入口。

示例:

访问 /api/,会看到:

python 复制代码
{
  "users": "http://127.0.0.1:8000/api/users/",
  "groups": "http://127.0.0.1:8000/api/groups/"
}

5. 自定义 Router

如果你需要定制路由规则,可以继承 SimpleRouter 并重写 routes 属性:

python 复制代码
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() 负责登记 prefixviewsetbasename,并保存到 self.registry

  • router.urls 在第一次访问时动态生成 URLConf,映射到 ViewSet 的标准动作。

  • DefaultRouterSimpleRouter 多了一个根 API 入口。

  • Router 本质上就是一个 URL 自动生成器,大大简化了手写路由的工作。

相关推荐
二等饼干~za89866811 小时前
碰一碰发视频系统源码开发搭建--技术分享
java·运维·服务器·重构·django·php·音视频
高洁0113 小时前
基于Tensorflow库的RNN模型预测实战
人工智能·python·算法·机器学习·django
luoluoal1 天前
基于python的RSA算法的数字签名生成软件(源码+文档)
python·mysql·django·毕业设计
牢七2 天前
5655869
django
秋氘渔3 天前
智演沙盘 —— 基于大模型的智能面试评估系统
python·mysql·django·drf
jcsx4 天前
如何将django项目发布为https
python·https·django
百锦再4 天前
京东云鼎入驻方案解读——通往协同的“高架桥”与“快速路”
android·java·python·rust·django·restful·京东云
Warren984 天前
datagrip新建oracle连接教程
数据库·windows·云原生·oracle·容器·kubernetes·django
韩立学长4 天前
【开题答辩实录分享】以《跳蚤市场二手物品交易推荐平台》为例进行选题答辩实录分享
python·django
飞天小蜈蚣5 天前
django的ulr注意事项、模板渲染
python·django·sqlite