手摸手,带你用Django REST Framework撸接口系列五(路由篇)
资源路由允许你快速声明给定的有足够控制器的所有公共路由。而不是为你的index…声明单独的路由,一个强大的路由能在一行代码中声明它们。
Django REST Framework系列文章
手摸手,带你用Django REST Framework撸接口系列一(基础篇)
手摸手,带你用Django REST Framework撸接口系列二(序列化器篇)
手摸手,带你用Django REST Framework撸接口系列三(视图篇)
手摸手,带你用Django REST Framework撸接口系列四(渲染器篇)
手摸手,带你用Django REST Framework撸接口系列五(路由篇)
手摸手,带你用Django REST Framework撸接口系列六(认证篇)
手摸手,带你用Django REST Framework撸接口系列七(权限篇)
手摸手,带你用Django REST Framework撸接口系列八(限流篇)
手摸手,带你用Django REST Framework撸接口系列九(过滤篇)
手摸手,带你用Django REST Framework撸接口系列十(排序篇)
手摸手,带你用Django REST Framework撸接口系列十一(分页篇)
手摸手,带你用Django REST Framework撸接口系列十二(异常处理篇)
手摸手,带你用Django REST Framework撸接口系列十三(自动生成接口文档篇)
某些Web框架(如Rails)提供了自动确定应用程序的URL应如何映射到处理传入请求的逻辑的功能。
REST框架添加了对自动URL路由到Django的支持,并为你提供了一种简单、快速和一致的方式来将视图逻辑连接到一组URL。
drf路由依赖于视图集,只有使用了视图集,才可以使用自动生成路由,路由系统可以自动完成增删改查,如果只是增删就不太需要引用
简单用法
下面是一个使用 SimpleRouter
的简单 URL 配置示例。
1 | from rest_framework import routers |
register()
方法有两个必须参数:
prefix
- 设置这组路由的前缀。viewset
- 设置对应的视图集类。或者,您也可以指定一个附加参数:
base_name
- 用于创建的 URL 名称的基础。如果未设置,将根据视图集的queryset
属性自动生成。请注意,如果视图集不包含queryset
属性,则在注册视图集时必须设置base_name
。
上面的例子会生成以下 URL 模式:
1 | URL pattern: ^users/$ Name: 'user-list' |
注意:
base_name
参数用于指定视图名称模式的初始部分。在上面的例子中,是user
或account
部分。
通常,您不需要指定 base_name
参数,但是如果您有一个视图集定义了自定义 get_queryset
方法,那么该视图集可能没有设置 .queryset
属性。如果此时尝试注册该视图,则会看到如下所示的错误:
1 | 'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute. |
'base_name'
参数未指定,并且无法自动确定视图中的名称,因为它没有’.queryset'
属性。
这时候就需要在注册视图集时显式设置 base_name
参数,因为它无法从模型名称中自动确定。
使用 include
与路由
路由实例上的 .urls
属性是一个标准的 URL patterns。关于如何包含这些 URL,有许多不同的样式。
例如,可以将 router.urls
附加到现有视图的列表中…
1 | router = routers.SimpleRouter() |
另外,你也可以使用 Django 的 include
函数,比如…
1 | urlpatterns = [ |
还可以设置 namespace。
1 | urlpatterns = [ |
如果对超链接序列化器使用命名空间,则还需要确保序列化器上的任何 view_name
参数都能正确反映命名空间。在上面的示例中,您需要为超链接到用户详细信息视图的序列化程序字段包含诸如 view_name='api:user-detail'
之类的参数。
额外的链接和操作
用 @detail_route
或 @list_route
装饰的 视图上的任何方法 也将被路由。例如,在 UserViewSet
类中给出这样的方法:
1 | from myapp.permissions import IsAdminOrIsSelf |
会生成以下URL模式:
1 | URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password' |
如果您不想使用默认生成的 URL 模式,则可以使用 url_path 参数对其进行自定义。
例如,如果您想将我们的自定义操作的URL更改为 ^users/{pk}/change-password/$
,则可以编写:
1 | from myapp.permissions import IsAdminOrIsSelf |
上面的例子现在将生成以下URL模式:
1 | URL pattern: ^users/{pk}/change-password/$ Name: 'user-change-password' |
如果您不想使用生成的默认名称,则可以使用 url_name 参数对其进行自定义。
例如,如果您想将自定义操作的名称更改为 'user-change-password'
,则可以编写:
1 | from myapp.permissions import IsAdminOrIsSelf |
上面的例子现在将生成以下URL模式:
1 | URL pattern: ^users/{pk}/set_password/$ Name: 'user-change-password' |
可以同时使用 url_path
和 url_name
参数。
API 参考
SimpleRouter
SimpleRouter
包含标准的 list
,create
,retrieve
,update
,partial_update
和 destroy
action。SimpleRouter
还支持视图集使用 @detail_route
或 @list_route
装饰器标记其他要路由的方法。
URL Style | HTTP Method | Action | URL Name |
---|---|---|---|
{prefix}/ | GET | list | {basename}-list |
POST | create | ||
{prefix}/{methodname}/ | GET, 或者由 methods 参数指定 | @list_route 装饰的方法 | {basename}-{methodname} |
{prefix}/{lookup}/ | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/ | GET, 或者由 methods 参数指定 | @detail_route 装饰的方法 | {basename}-{methodname} |
默认情况下,由 SimpleRouter
创建的 URL 附加了尾部斜杠。在实例化路由器时,可以通过将 trailing_slash
参数设置为 False
来修改此行为。例如:
1 | router = SimpleRouter(trailing_slash=False) |
尾部斜杠在 Django 中是常规的,但在其他一些框架(如 Rails)中默认不使用。选择使用哪种风格在很大程度上是一个偏好问题,尽管一些 JavaScript 框架可能会期望特定的路由风格。
SimpleRouter
将匹配包含除斜杠和句点字符以外的任何字符的 lookup 值。对于更严格(或宽松)的 lookup pattern,请在视图集上设置 lookup_value_regex
属性。例如,您可以将 lookup 限制为有效的 UUID:
1 | class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): |
DefaultRouter
DefaultRouter
与上面的 SimpleRouter
相似,但还包含一个默认的 API 根视图,该视图返回一个包含指向所有列表视图的超链接的响应。它还为可选的 .json
风格格式后缀生成路由。
URL Style | HTTP Method | Action | URL Name |
---|---|---|---|
[.format] | GET | 自动生成的根视图 | api-root |
{prefix}/[.format] | GET | list | {basename}-list |
POST | create | ||
{prefix}/{methodname}/[.format] | GET, 或者由 methods 参数指定 | @list_route 装饰的方法 | {basename}-{methodname} |
{prefix}/{lookup}/[.format] | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/[.format] | GET, 或者由 methods 参数指定 | @detail_route 装饰的方法 | {basename}-{methodname} |
注意:我在使用 3.7.7 版本时,发现要写成
{prefix}[.format]/
风格才能访问,{prefix}/[.format]
风格会报 404,不知道是我设置问题还是官方更新了。
与 SimpleRouter
一样,通过在实例化 DefaultRouter
时将 trailing_slash
参数设置为 False
,可以删除 URL 路径上的尾部斜杠。
1 | router = DefaultRouter(trailing_slash=False) |
SimpleRouter和DefaultRouter区别
DefaultRouter
与上面的 SimpleRouter
相似,但还包含一个默认的 API 根视图,该视图返回一个包含指向所有列表视图的超链接的响应。它还为可选的 .json
风格格式后缀生成路由。
关于这两个哥们的区别其实上面已经写得很清楚了,只是只从路由规则上看刚接触的还是有点懵,我这里实际来演示下。
SimpleRouter生成路由
1 | urlpatterns = [ |
我们通过命令行查看下生成后的路由,我这里安装了django_extensions,可以使用./manager.py show_urls查看路由
1 | (python3_mall) Tony-iMac:djangoProject tony$ ./manage.py show_urls |
可以看到就是简单的生成了两个路由,一个针对对象列表,一个针对对象,没什么可说的。
DefaultRouter生成路由
根路由
1 | urlpatterns = [ |
查看生成的路由
1 | (python3_mall) Tony-iMac:djangoProject tony$ ./manage.py show_urls |
可以看到竟然生成了6个路由,除了生成的4个关于对象列表和单个对象的路由外,还生成了一对根路由。
我们访问下根路由看会发生什么事情,从访问结果来看直接给我们返回了一个列表式图的超链接。
因为我路由只包含了Article一个视图集,看不出来什么,我再添加进去一个视图集进去。
1 | urlpatterns = [ |
再次访问试试,这次明显能看出来了该根路由视图返回一个包含指向所有列表视图的超链接的响应
format
1 | /\.<format>/ rest_framework.routers.APIRootView api-root |
我们注意到它还生成了一堆.format的路由规则,我们还是以根路由为例,我们加上.json后缀看看,发现输出的列表也自带了.json后缀
所以我们访问列表页和详情页试试
所以,上方的它还为可选的 .json
风格格式后缀生成路由这句话得到了验证。
自定义路由
自定义路由并不是你经常需要做的事情,但是如果你对 API 的 URL 是如何构建的有特定的要求的话,它会很有用。这样做可以让你以可重用的方式封装 URL 结构,确保你不必为每个新视图明确编写 URL 模式。
实现自定义路由的最简单方法是对现有路由类之一进行子类化。.routes
属性用于对将映射到每个视图集的 URL 模式进行模板化。.Routes
属性是一个 Route
列表(Route
的是一个 namedtuple)。
Route
命名元组的参数:
url : 表示要路由的 URL 的字符串。可以包含以下格式字符串:
{prefix}
- 路由的 URL 前缀。
{lookup}
- 匹配单个实例的 lookup field。
{trailing_slash}
- 可以是 ‘/‘ 或空字符串,具体取决于trailing_slash
参数。
mapping : HTTP 方法名称与视图方法的映射
name: 用于调用 reverse
时的 URL 的名称。可能包含以下格式字符串:
{basename}
- 创建的 URL 名称的基础。
initkwargs: 实例化视图时应传递的任何其他参数的字典。注意,suffix
参数被保留用于标识视图集类型,在生成视图名称和 breadcrumb 链接时使用。
自定义动态路由
你还可以自定义 @list_route
和 @detail_route
装饰器的路由方式。要路由这两个装饰器中的一个或两个,请在 .routes
列表中包含一个 DynamicListRoute
和/或 DynamicDetailRoute
(别忘了类型是 namedtuple)。
DynamicListRoute
和 DynamicDetailRoute
的参数是:
url: 表示要路由的 URL 的字符串。可以包含与
Route
相同的格式字符串,并且还接受{methodname}
和{methodnamehyphen}
格式的字符串。name: 用于调用
reverse
时的名称。可以包含以下格式字符串:{basename}
,{methodname}
和{methodnamehyphen}
。initkwargs: 实例化视图时应传递的任何其他参数的字典。
举个栗子
以下示例只会路由 list
和 retrieve
action,并且不使用尾部斜杠约定。
1 | from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter |
让我们来看看 CustomReadOnlyRouter
为一个简单的视图集生成的路由。
views.py
:
1 | class UserViewSet(viewsets.ReadOnlyModelViewSet): |
urls.py
:
1 | router = CustomReadOnlyRouter() |
将生成以下映射…
URL | HTTP Method | Action | URL Name |
---|---|---|---|
/users | GET | list | user-list |
/users/{username} | GET | retrieve | user-detail |
/users/{username}/group-names | GET | group_names | user-group-names |
有关设置 .routes
属性的另一个示例,请参阅 SimpleRouter
类的源代码。
自定义路由器进阶
如果想提供完全自定义的行为,可以继承 BaseRouter
并覆盖 get_urls(self)
方法。该方法应检查已注册的视图集并返回一组 URL 模式。可以通过访问 self.registry
属性来检查注册的 prefix,viewset 和 basename tuples。
你可能还想覆盖 get_default_base_name(self,viewset)
方法,或者在向路由注册视图集时始终显式设置 base_name
参数。
参考
DRF频率组件的使用方式
DRF视图组件使用
DRF分页器组件
DRF认证组件使用流程
DRF权限组件代码实现
DRF路由注册器组件
DRF响应器组件
DRF自定义用户token
DjangoRestFramework view.py文件书写流程
Django REST Framework完整开发api示例
Django Rest Framework读取用户IP写入数据表
Access-Control-Allow-Origin跨域问题
Django REST Framework系列文章
手摸手,带你用Django REST Framework撸接口系列一(基础篇)
手摸手,带你用Django REST Framework撸接口系列二(序列化器篇)
手摸手,带你用Django REST Framework撸接口系列三(视图篇)
手摸手,带你用Django REST Framework撸接口系列四(渲染器篇)
手摸手,带你用Django REST Framework撸接口系列五(路由篇)
手摸手,带你用Django REST Framework撸接口系列六(认证篇)
手摸手,带你用Django REST Framework撸接口系列七(权限篇)
手摸手,带你用Django REST Framework撸接口系列八(限流篇)
手摸手,带你用Django REST Framework撸接口系列九(过滤篇)
手摸手,带你用Django REST Framework撸接口系列十(排序篇)
手摸手,带你用Django REST Framework撸接口系列十一(分页篇)
手摸手,带你用Django REST Framework撸接口系列十二(异常处理篇)
手摸手,带你用Django REST Framework撸接口系列十三(自动生成接口文档篇)