Django drf 視圖集和路由器

2021-12-08 15:39 更新

REST框架包括一個用于處理ViewSets的抽象,它允許開發(fā)人員集中精力對API的狀態(tài)和交互進行建模,并根據(jù)常規(guī)約定自動處理URL構(gòu)造。

ViewSet類與View類幾乎相同,不同之處在于它們提供諸如read或update之類的操作,而不是get或put等方法處理程序。

最后一個ViewSet類只綁定到一組方法處理程序,當(dāng)它被實例化成一組視圖的時候,通常通過使用一個Router類來處理自己定義URL conf的復(fù)雜性。

使用ViewSets重構(gòu)

我們看一下目前的視圖,把它們重構(gòu)成視圖集。

首先讓我們將UserList和UserDetail視圖重構(gòu)為一個UserViewSet。我們可以刪除這兩個視圖,并用一個類替換它們:

from rest_framework import viewsets

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    此視圖自動提供`list`和`detail`操作。
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

這里,我們使用ReadOnlyModelViewSet類來自動提供默認(rèn)的“只讀”操作。我們?nèi)匀幌袷褂贸R?guī)視圖那樣設(shè)置queryset和serializer_class屬性,但我們不再需要向兩個不同的類提供相同的信息。

接下來,我們將替換SnippetList,SnippetDetail和SnippetHighlight視圖類。我們可以刪除三個視圖,并再次用一個類替換它們。

from rest_framework.decorators import detail_route

class SnippetViewSet(viewsets.ModelViewSet):
    """
    此視圖自動提供`list`,`create`,`retrieve`,`update`和`destroy`操作。

    另外我們還提供了一個額外的`highlight`操作。
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    @detail_route(renderer_classes=[renderers.StaticHTMLRenderer])
   #@action(detail=True, 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類來獲取完整的默認(rèn)讀寫操作。

請注意,我們還使用@detail_route裝飾器創(chuàng)建一個名為highlight的自定義操作。這個裝飾器可用于添加不符合標(biāo)準(zhǔn)create/update/delete樣式的任何自定義路徑。

默認(rèn)情況下,使用@detail_route裝飾器的自定義操作將響應(yīng)GET請求。如果我們想要一個響應(yīng)POST請求的動作,我們可以使用methods參數(shù)。

默認(rèn)情況下,自定義操作的URL取決于方法名稱本身。如果要更改URL的構(gòu)造方式,可以為裝飾器設(shè)置url_path關(guān)鍵字參數(shù)。

在 Django REST framework 3.8中,使用?action ?裝飾器替換 ?list_route ?和 ?detail_route ?。 ?list_route ?和 ?detail_route? 已合并為單個 ?action ?裝飾器。這改進了視圖集操作內(nèi)省,并允許在未來版本中的可瀏覽 API 中顯示額外的操作。

?list_route ?和 ?detail_route ?現(xiàn)在都在等待棄用。它們將在 3.9 中被棄用,并在 3.10 中被完全刪除。

新的 ?action ?裝飾器采用布爾 ?detail? 參數(shù)。

  • 使用? @action(detail=True)? 替換 ?detail_route?。
  • 使用 ?@action(detail=False)? 替換 ?list_route?。

明確地將ViewSets綁定到URL

當(dāng)我們定義URLConf時,處理程序方法只能綁定到那些動作上。 要了解在幕后發(fā)生的事情,首先顯式地從我們的視圖集中創(chuàng)建一組視圖。

在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'
})

請注意,我們是如何通過將http方法綁定到每個視圖所需的操作,從每個ViewSet類創(chuàng)建多個視圖的。

現(xiàn)在我們將資源綁定到具體的視圖中,我們可以像往常一樣在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類,我們實際上不需要自己設(shè)計URL。將資源連接到視圖和url的約定可以使用Router類自動處理。我們需要做的就是使用路由器注冊相應(yīng)的視圖集,然后讓它執(zhí)行其余操作。

這是我們重寫的urls.py文件。

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

# 創(chuàng)建路由器并注冊我們的視圖。
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
router.register(r'users', views.UserViewSet)

# API URL現(xiàn)在由路由器自動確定。
# 另外,我們還要包含可瀏覽的API的登錄URL。
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

使用路由器注冊viewsets類似于提供urlpattern。我們包含兩個參數(shù) - 視圖的URL前綴和視圖本身。

我們使用的DefaultRouter類也會自動為我們創(chuàng)建API根視圖,因此我們現(xiàn)在可以從我們的views模塊中刪除api_root方法。

視圖(views)vs視圖集(viewsets)之間的權(quán)衡

使用視圖集可以是一個非常有用的抽象。它有助于確保URL約定在你的API中保持一致,最大限度地減少編寫所需的代碼量,讓你能夠?qū)W⒂贏PI提供的交互和表示,而不是URLconf的細(xì)節(jié)。

這并不意味著采用視圖集總是正確的方法。在使用基于類的視圖而不是基于函數(shù)的視圖時,有一個類似的權(quán)衡要考慮。使用視圖集不像單獨構(gòu)建視圖那樣明確。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號