做者:HelloGitHub-追夢人物web
在 RESTful 架構中,對資源的常規操做無非就是查詢、新增、修改、刪除等這麼幾種。爲此,django-rest-framework 分別提供了對應通用類視圖函數。可是,若是對同一個資源的不一樣操做邏輯分散在各個視圖函數中,從邏輯上來講不太合理,實際中管理起來也不是很方便,還會產生不少重複性的代碼。所以,django-rest-framework 引入了視圖集(Viewsets),把對同一個資源的不一樣操做,集中到一個類中。一樣的,針對 Web 開發中的常見邏輯,django-rest-framework 也提供了通用視圖集,進一步簡化開發工做。django
使用視圖集的一個更大的好處,就是能夠配合 django-rest-framework 提供的路由器(router),自動生成 API 的 URL,不須要咱們再手工將 URL 模式和視圖函數綁定了。因此大部分狀況下,即便對資源只有一種操做,咱們通常也會使用視圖集。api
先來看看博客首頁文章列表視圖集的代碼:服務器
blog/views.py
from rest_framework import viewsets from rest_framework import mixins class PostViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = PostListSerializer queryset = Post.objects.all() pagination_class = PageNumberPagination permission_classes = [AllowAny] 複製代碼
全部視圖集都要繼承視圖集的基類。視圖集也有 2 個基類:ViewSet
和 GenericViewSet
,前者是最基本的視圖集類,後者拓展自前者,拓展了不少 Web 開發中的通用邏輯。架構
要注意一點的是,視圖集基類提供的是除資源操做之外的通用邏輯(例如 HTTP 請求預處理、HTTP 響應後處理、認證、鑑權等),而對於資源的操做(如序列化、更新、刪除資源等)則放在相應的 Mixin 混入類裏。django-rest-framework 提供了資源操做的 5 個混入類,分別對應資源的建立、查詢、更新、刪除。app
CreateModelMixin編輯器
提供 create
方法用於建立資源函數
ListModelMixin 和 RetrieveModelMixinpost
提供 list 和 retrieve,分別用於獲取資源列表和單個資源url
UpdateModelMixin
提供 update 方法用於更新資源
DestroyModelMixin
提供 destroy 方法用於刪除資源
此外,create、list、retrieve、update、destroy 的方法名會被映射爲對應的 action,稱爲對資源操做的一個動做。前面說到視圖集的一個最大好處就是可使用路由器(router)自動生成 URL 模式。URL 正是根據 action 的類型來生成的,後面咱們會具體說到。
好了,視圖集已經建立完畢,接下來咱們從視圖集生成視圖函數,並綁定 URL。
blog/views.py
index = PostViewSet.as_view({'get': 'list'}) 複製代碼
blog/urls.py
app_name = "blog" urlpatterns = [ # ... # path("api/index/", views.IndexPostListAPIView.as_view()), path("api/index/", index), ] 複製代碼
等等,不是說視圖集的一個好處是使用路由器自動生成 URL 模式嗎?爲何還要手工建立視圖函數,而後綁定 URL?
別急,這裏只是演示一下如何從視圖集生成視圖函數並綁定 URL,這樣可以幫助你更好地理解視圖集的工做方式。事實上,使用路由器自動生成 URL 模式時,路由器內部就是採用了和上面手工生成視圖函數並綁定 URL 同樣的方式。
路由器的使用很是簡單,咱們在 初始化 RESTful API 風格的博客系統 中引入了 DefaultRouter 以開啓 API 交互後臺,DefaultRouter 實例化時默認幫咱們註冊了一個 API 交互後臺的根視圖,如今要註冊一個新的視圖,調用其 register
方法就能夠了:
blogproject/urls.py
from blog.views import PostViewSet from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register(r'posts', PostViewSet, basename='post') 複製代碼
Django-rest-framework 提供 SimpleRouter
和 DefaultRouter
兩個路由器類,後者是對前者的拓展,所以一般狀況下都使用後者。DefaultRouter 增長了一個 api 的根路由,訪問根路由的 URL 就能夠看到其餘註冊的所有 api 路由,一下子咱們將會看到具體的效果。
視圖集自動生成 URL 模式很是簡單,只需實例化一個路由器,而後調用其 register
方法,這個方法接收 3 個參數,第一個參數是 URL 前綴,全部從註冊的視圖集生成的 URL 都會帶有這個前綴。第二個參數就是視圖集,第三個參數 basename 用於指定視圖集生成的視圖函數名的前綴。在 django 的 URL 中,一條路由一般由 URL 模式,對應的視圖函數和視圖函數名組成。視圖函數名的做用主要用於解析視圖函數所對應的 URL。視圖集最終會被轉爲多個視圖函數,那麼這個視圖函數的名字是什麼呢?django-rest-framework 的默認生成規則是 basename-action。
例如這裏 basename='post'
,列出資源列表的 action 爲 list(見上一篇教程中關於 action 的講解),因此生成的獲取文章資源列表的視圖函數名爲 post-list,使用 reverse('post-list') 就能夠解析出獲取文章資源列表的 API(URL)。
basename 能夠不指定,django-rest-framework 會自動從視圖集 get_queryset 方法返回的結果所關聯的 model 獲取一個默認值,其值爲 model 名小寫。不過,根據 Python 之禪,顯式優於隱式,所以即便你設置的 basename 和 django-rest-framework 默認生成的同樣,也比不指定要好。
剛纔說了,咱們使用 DefaultRouter 這個路由器,它會自動幫咱們註冊一個根路由,來看看根路由下有什麼。
運行開發服務器,訪問 http://127.0.0.1:8000/api/,界面以下:
django-rest-framework 爲咱們自動生成了 API 交互後臺,在這個界面中能夠和咱們建立的 API 交互,很是方便。API 交互後臺首頁是全部註冊的視圖集對應的 URL。目前只有一條 /api/posts/,點擊超連接進去,能夠看到 /api/posts/ 的返回結果,即所有文章列表。
可是,目前咱們的 api 一股腦將所有文章列表的返回了。可是咱們的博客文章列表是有分頁功能的,接下來咱們就使用 django-rest-framework 提供的分頁輔助類,一行代碼就能夠完成分頁功能。