Django REST FrameWork中文教程6: ViewSets&Routers

REST框架包括一個處理的抽象ViewSets,它容許開發人員集中精力對API的狀態和交互進行建模,並根據常規約定使URL構造自動處理。html

ViewSet類是幾乎一樣的事情View類,但他們提供諸如操做read,或者update,而不是方法處理,如get或put。django

一個ViewSet類在最後一刻被綁定到一組方法處理程序,當它被實例化成一組視圖時,一般經過使用一個Router類來處理爲你定義URL conf的複雜性。segmentfault

重構使用ViewSets
咱們來看一下咱們目前的觀點,並把它們重構成視圖集。api

首先,讓咱們來重構咱們UserList和UserDetail意見歸入一個單一的UserViewSet。咱們能夠刪除這兩個視圖,並將其替換爲單個類:框架

from rest_framework import viewsets

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    This viewset automatically provides `list` and `detail` actions.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

在這裏,咱們使用ReadOnlyModelViewSet該類來自動提供默認的「只讀」操做。咱們仍然正如咱們使用常規視圖同樣設置queryset和serializer_class屬性,可是咱們再也不須要向兩個不一樣的類提供相同的信息。ide

接下來咱們要更換SnippetList,SnippetDetail和SnippetHighlight視圖類。咱們能夠刪除三個視圖,並再次替換爲單個類。函數

from rest_framework.decorators import detail_route

class SnippetViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.

    Additionally we also provide an extra `highlight` action.
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    @detail_route(renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

這一次,咱們已經使用了ModelViewSet類來獲取完整的默認讀寫操做。工具

請注意,咱們還使用@detail_route裝飾器建立一個名爲的自定義操做highlight。此裝飾器可用於添加不適合標準create/ update/ delete樣式的任何自定義端點。post

默認狀況下,使用@detail_route裝飾器的自定義操做將響應GET請求。methods若是咱們想要一個響應POST請求的動做,咱們可使用該參數。url

默認狀況下,自定義操做的URL取決於方法名稱自己。若是要更改url應該構造的方式,能夠將url_path做爲decorator的關鍵字參數。

明確地將ViewSets綁定到URL
當咱們定義URLConf時,處理程序方法只會被綁定到動做上。看看發生什麼事情,讓咱們首先從ViewSets中明確建立一組視圖。

在urls.py文件中,咱們將咱們的ViewSet類綁定到一組具體的視圖中。

from snippets.views import SnippetViewSet, UserViewSet, api_root
from rest_framework import renderers

snippet_list = SnippetViewSet.as_view({
    'get': 'list',
    'post': 'create'
})
snippet_detail = SnippetViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
})
snippet_highlight = SnippetViewSet.as_view({
    'get': 'highlight'
}, renderer_classes=[renderers.StaticHTMLRenderer])
user_list = UserViewSet.as_view({
    'get': 'list'
})
user_detail = UserViewSet.as_view({
    'get': 'retrieve'
})

請注意,咱們如何ViewSet經過將http方法綁定到每一個視圖所需的操做,從每一個類建立多個視圖。

如今咱們將資源綁定到具體的視圖中,咱們能夠像往常同樣使用URL conf註冊視圖。

urlpatterns = format_suffix_patterns([
    url(r'^$', api_root),
    url(r'^snippets/$', snippet_list, name='snippet-list'),
    url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),
    url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
    url(r'^users/$', user_list, name='user-list'),
    url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail')
])

使用路由器
由於咱們使用ViewSet類而不是View類,咱們實際上不須要設計本身的URL。將資源鏈接到視圖和網址的約定可使用Router類自動處理。咱們須要作的就是使用路由器註冊相應的視圖集,而後讓它執行其他操做。

這是咱們的從新連線的urls.py文件。

from django.conf.urls import url, include
from snippets import views
from rest_framework.routers import DefaultRouter

# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
router.register(r'users', views.UserViewSet)

# The API URLs are now determined automatically by the router.
# Additionally, we include the login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

與路由器註冊視圖與提供urlpattern相似。咱們包括兩個參數 - 視圖的URL前綴和視圖自己。

DefaultRouter咱們使用的類也會自動爲咱們建立API根視圖,所以咱們如今能夠api_root從咱們的views模塊中刪除該方法。

視圖vs視圖之間的權衡
使用視圖能夠是一個很是有用的抽象。它有助於確保您的API中的URL約定是一致的,最大限度地減小您須要編寫的代碼量,並容許您專一於API提供的交互和表示,而不是URL conf的具體內容。

這並不意味着老是採起正確的方法。在使用基於類的視圖而不是基於函數的視圖時,須要考慮一組相似的權衡。使用viewsets比單獨構建視圖不太明確。

在本教程的第7部分中,咱們將介紹如何添加API模式,並使用客戶端庫或命令行工具與API進行交互。

Django REST FrameWork中文文檔目錄:
Django REST FrameWork 中文教程1:序列化

Django REST FrameWork 中文教程2:請求和響應

Django REST FrameWork 中文教程3:基於類的視圖

Django REST FrameWork 中文教程4:驗證和權限

Django REST FrameWork 中文教程5:關係和超連接API

Django REST FrameWork 中文教程6: ViewSets&Routers

Django REST FrameWork 中文教程7:模式和客戶端庫

相關文章
相關標籤/搜索