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

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


Router 路由SimpleRouter

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

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

urls.py 中进行配置路由。

from rest_framework import routersrouter = 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)



include 方法

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

url.py 父级路由文件。

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

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

GET:获取数据详情/列表PUT:修改数据POST:新增数据DLETE:删除数据

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

from rest_framework.decorators import actionfrom rest_framework.viewsets import ModelViewSetclass 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 reversefrom rest_framework.views import APIViewfrom django.utils.timezone import nowclass 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)应用示例

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

在这里插入图片描述


include 应用

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

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

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

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

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

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

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