在Django Web API 开发中设计中符合 RESTful 风格的 API 路由。通常最好是从 Web API 返回绝对 URL 比如 http://xxxx.com/data,而不是相对 URL 比如 /data 。

REST 框架添加了对 Django 的自动 URL 路由的支持,并为提供了一种简单、快速且一致的方式来将视图逻辑连接到一组 URL。

用route命令查看自己主机的路由表(DRF3.xURLs)(1)

Router 路由Simplerouter

使用已经定义好的 ModelNameViewSet 注册 URL,使用 register() 方法必须使用参数:

urls.py 中进行配置路由。

from rest_framework import routers router = routers.SimpleRouter() router.register(r'apps/modelname', ModelNameViewSet) urlpatterns = router.urls

视图集实现了获取列表/获取详情/新增/删除/修改的方法, 定义路由将会解析成。

URL

格式请求

方法请求

说明视图集方法

^article_settings/article$

GET

获取列表

list()

^article_settings/article/{pk}$

GET

获取详情

retrieve()

^article_settings/article$

POST

新增

create()

^article_settings/article/{pk}$

PUT

更新

update()

^article_settings/article/{pk}$

DELETE

删除

destroy()

默认情况下路由都需要添加符号 / 作为路由结尾,修改该规则需要修改参数。

router = SimpleRouter(trailing_slash=False)

用route命令查看自己主机的路由表(DRF3.xURLs)(2)

include 方法

使用 urlpatterns = Router.urls 的方式注册路由对象通常会使用 include 进行路由注册, 并且在 Django 中自定义的视图不需要使用 SimpleRouter 进行注册。

url.py 父级路由文件。

from django.conf.urls import url from django.urls import include from rest_framework import routers router = routers.SimpleRouter() router.register(r'apps/modelname', ModelNameViewSet) urlpatterns = [ ..., # 其他路由配置 url(r'^', include(router.urls)), ]

路由绑定其他操作

对访问数据的配置可能有以下几个方法处理:

默认情况下你生成的 URL 是根据函数名称生成,可以通过 url_name 和 url_path 制定路由的后缀名称,可以通过 permission_classes 来制定访问权限。

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): ...

DefaultRouter

与 SimpleRouter 类似,但会包含一个默认的 API 根视图,返回一个包含所有列表视图的超链接响应数据。

该路由的路径也会使用 / 结尾,可以用 trailing_slash=False 修改

router = DefaultRouter(trailing_slash=False)

自定义路由器

需要自定义 URL 格式的时候使用,实现自定义路由是将现有路由作为子类之一。其 .routes 属性是 Route 的命名元组的列表数据。

Route 元祖参数

解释说明

url

代表需要路由的 URL 字符串,例如:用于这组路由器的前缀字符串 "{prefix}";用于单个实例匹配的字符串"{lookup}"的ID;根据 trailing_slash 参数制定结尾字符"{trailing_slash}"

mapping

HTTP 方法名称到视图方法的映射

name

reverse 呼叫用使用的 URL 名称,例如:用于创建 URL 名称的基础字符"{basename}"

initkwargs

实例化视图需要的参数字典

自定义解析路线

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

detail 参数

解释说明

url

一个代表路由 URL 的字符串,可能会包含和 Route 相同格式的字符串,并接受一个 "{url_path}" 格式的字符串

name

reverse 调用中使用的 URL 名称, 例如:用于创建 URL 的名称基础"{basename}";提供给 @action 的 "{url_name}"

initkwargs

实例化试图需要的参数字典

Returning URLs返回链接

框架提供了两个实用函数, 使得从 Web API 返回绝对 URL 变得更加简单。如果使用那么自描述 API 将能够自动为您超链接其输出,这使得浏览 API 更加容易。

用途: 1. 更加明确。 2. 为 API 客户端减少了工作。 3. 当在 JSON 等, 没有本机 URL 类型的表示中找到字符串时, 其含义没有任何歧义。 4. 使用超链接标记 HTML 表示之类的事情变得很容易。

reverse

具有与 django.url.reverse 相同的行为,但它返回一个完全限定的 URL (使用请求确定主机和端口)。

reverse(viewname, *args, **kwargs)

将请求作为函数的关键字参数包括在内。

from rest_framework.reverse import reverse from rest_framework.views import APIView from django.utils.timezone import now class APIrootView(APIView): def get(self, request): year = now().year data = { ... 'year-summary-url': reverse('year-summary', args=[year], request=request) } return Response(data)

reverse_lazy

具有和 django.url.reverse_lazy 相同的行为,它返回一个完全限定的 URL (使用请求来确定主机和端口)。

reverse_lazy(viewname, *args, **kwargs)

应该将请求作为关键字参数包含到函数中。

api_root = reverse_lazy('api-root', request=request)

应用示例

路由经常会和返回链接一起使用,构建完整的项目访问网址的跳转内容。

用route命令查看自己主机的路由表(DRF3.xURLs)(3)

在这里插入图片描述

include 应用

在项目的 urls.py 中配置项目的路由,并且 include 各个应用下的 url.py。

from rest_framework.routers import DefaultRouter router = DefaultRouter() # 建立一个路由对象 urlpatterns = [ ...... # include 各个模块的内容 path('app01/', include("app01.urls")), ...... ]

应用 url 路由

from rest_framework.routers import DefaultRouter from .views import * # 自动生成路由方法 router = DefaultRouter() # apps.articles 下的全部路由方法 router.register('ArticleCategory', ArticleCategoryViewSet, 'ArticleCategory') router.register('ArticleItem', ArticleItemViewSet, 'ArticleItem') ...... urlpatterns = [ ] urlpatterns = router.urls

reverse 路由解析

重新定向通过路由返回页面。

from django.urls import reverse from django.shortcuts import redirect def xxxx(request): ...... return redirect(reverse('home'))

重新定向通过路由携带参数返回页面。

from django.urls import reverse from django.shortcuts import redirect def xxxx(request): ...... reverse('slug', args=(data,))

,