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={}
        )
    ]
複製代碼
相關文章
相關標籤/搜索