Rest-framework专栏讲解(七):Router

MedusaSorcerer的博客


点击跳转到 Rest-Framework 专栏目录

在开发中咱们会设计好符合 Restful 风格的 API, 那框架已经帮咱们提供了这些快捷方式。html

SimpleRouter

在咱们定义好了 MedusaBlogViewSet 的状况下, 咱们注册 URL 的时候仅须要:python

#!/usr/bin/env python
# _*_ Coding: UTF-8 _*_
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'medusa/blog', MedusaBlogViewSet)
urlpatterns = router.urls
复制代码

register() 有两个强制性的参数:django

  • prefix:用于这组路由的 URL 前缀字符串, 用于路由匹配
  • viewset:你定义的视图集

若是你的视图集实现了获取列表/获取详情/新增/删除/修改的方法, 那你定义路由将会解析成这样:api

URL 格式 请求方法 请求说明 视图集方法
^medusa/blog$ GET 获取列表 list()
^medusa/blog/{pk}$ GET 获取详情 retrieve()
^medusa/blog$ POST 新增 create()
^medusa/blog/{pk}$ PUT 更新 update()
^medusa/blog/{pk}$ DELETE 删除 destroy()

在你的视图集没有指定 queryset 属性或者自定义了 get_queryset() 方法的时候, 你可能会看到这样一条错误信息:app

'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
复制代码

因此你须要指定一个可选参数:basename, 默认状况下你不须要手动指定它的值, 它是建立 URL 名称的基础属性, 通常是用你指定的 queryset 属性值自动设置的。框架

默认状况下路由都须要添加 / 做为路由结尾, 你也能够修改该规则, 只须要修改参数 trailing_slash=False 便可:函数

router = SimpleRouter(trailing_slash=False)
复制代码

该路由器生成 URL 的方式: post

include

在上面的例子中, 咱们使用了 urlpatterns = router.urls 的方式注册了路由对象, 咱们一般会使用 include 进行路由注册, 在 Django 中可能有一些咱们自定义的视图, 不须要使用 SimpleRouter 进行注册:url

#!/usr/bin/env python
# _*_ Coding: UTF-8 _*_
from django.conf.urls import url
from django.urls import include
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'medusa/blog', MedusaBlogViewSet)

urlpatterns = [
    ...,  # 其余路由配置
    url(r'^', include(router.urls)),
]
复制代码

路由绑定其余操做

例如你的项目安排上, 安排关于用户模块是在配置的界面, 那么你的路由多是这样的:spa

/api/v1.0/configure/user
复制代码

那我对用户的配置可能有如下几个方法处理:

  • GET:获取用户详情/列表
  • PUT:修改用户信息
  • POST:新增用户信息
  • DELETE:删除用户信息

问题来了, 若是我不想建立一个新的关于用户的视图类, 可是我又想增长一个修改密码的 API 接口怎么办? 若是你从事过其余产品 API 调度工做的时候, 你可能会浮现这样类型的接口:

/api/v1.0/configure/user/1/reset
复制代码

很规范的接口方式, 那你在你的 ViewSet 里怎么体现呢?

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
from rest_framework.decorators import action
from rest_framework.viewsets import ModelViewSet


class UserViewSet(ModelViewSet):
    ...

 @action(methods=['post'], detail=True)
    def reset(self, request, pk=None):
        ...
复制代码

是的, 使用 action 装饰器装饰, 并指定参数便可, 默认状况下你生成的 URL 是根据你的函数名称生成了, 你也能够经过 url_nameurl_path 制定路由的后缀名称, 也能够经过 permission_classes 来制定用户访问权限。

DefaultRouter

这个路由器和 SimpleRouter 很相似, 但会包含一个默认的 API 根视图, 返回一个包含全部列表视图的超连接响应数据。 固然, 该路由的路径也会使用 / 结尾, 你能够用 trailing_slash=False 来弃用该规则:

router = DefaultRouter(trailing_slash=False)
复制代码

该路由生成 URL 的方式:

自定义路由器

其实在开发中这不是你使用路由器的最好方式, 可是在你须要自定义 URL 格式的时候使用这个方式将会变得颇有效, 而实现自定义路由是将现有路由做为子类之一, 其 .routes 属性是 Route 的命名元组的列表数据, 功能是用于模板化将映射到每一个视图集的 URL 模式。 Route 命名元祖的参数有:

  • url:表明须要路由的 URL 字符串, 你可能须要这样字符串
    • "{prefix}":用于这组路由器的前缀字符串
    • "{lookup}":用于单个实例匹配的字符串, 如ID
    • "{trailing_slash}":根据 trailing_slash 参数制定结尾字符
  • mapping:HTTP 方法名称到视图方法的映射
  • namereverse 呼叫用使用的 URL 名称,你可能须要这样的字符串
    • "{basename}":用于建立 URL 名称的基础字符
  • initkwargs:实例化视图须要的参数字典

其实以上文字内容是官方文档的描述内容加上我本身的理解装饰了一下, 可是看到这几行字的描述信息, 确实是不知道它的功能到底怎么样定义, 恰好看到某位大佬的博客, 参考并实践了一下:

附参考的博客地址:www.cnblogs.com/liubiao/p/6…

自定义解析路线

在使用 @action 的时候你也能够自定义路由方式, .routes 的列表是包含 DynamicRoute 命名的元组, 将 detail 参数设置为适用于基于列表的路由和基于详细信息的路由, DynamicRoute 除了 detail 参数:

  • url:一个表明路由 URL 的字符串, 可能会包含和 Route 相同格式的字符串, 并接受一个 "{url_path}" 格式的字符串
  • namereverse 呼叫中使用的 URL 名称, 你可能须要如下格式的字符串:
    • "{basename}":用于建立 URL 的名称基础
    • "{url_name}":提供给 @actionurl_name
  • initkwargs:实例化试图须要的参数字典
#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
from rest_framework.routers import Route, DynamicRoute, SimpleRouter


class CustomReadOnlyRouter(SimpleRouter):
    """ A router for read-only APIs, which doesn't use trailing slashes. """
    routes = [
        Route(
            url=r'^{prefix}$',
            mapping={'get': 'list'},
            name='{basename}-list',
            detail=False,
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}$',
            mapping={'get': 'retrieve'},
            name='{basename}-detail',
            detail=True,
            initkwargs={'suffix': 'Detail'}
        ),
        DynamicRoute(
            url=r'^{prefix}/{lookup}/{url_path}$',
            name='{basename}-{url_name}',
            detail=True,
            initkwargs={}
        )
    ]
复制代码
相关文章
相关标签/搜索