Django REST framework API 指南(6):路由

Django REST framework API 指南(1):請求
Django REST framework API 指南(2):響應
Django REST framework API 指南(3):視圖
Django REST framework API 指南(4):通用視圖
Django REST framework API 指南(5):視圖集
Django REST framework API 指南(6):路由
Django REST framework API 指南(7):解析python

官方原文連接git

路由

一些 Web 框架(如 Rails)提供了一種可以自動肯定應用程序的 URL 如何映射處處理請求的功能。github

REST framework 增長了對 Django 自動 URL 路由的支持,並提供了一種將視圖邏輯鏈接到一組 URL 的簡單,高效和一致的方式。django

用法

下面是一個使用 SimpleRouter 的簡單 URL 配置示例。json

from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
複製代碼

register() 方法有兩個必須參數:api

  • prefix - 設置這組路由的前綴。
  • viewset - 設置對應的視圖集類。

或者,您也能夠指定一個附加參數:app

  • base_name - 用於建立的 URL 名稱的基礎。若是未設置,將根據視圖集的 queryset 屬性自動生成。請注意,若是視圖集不包含 queryset 屬性,則在註冊視圖集時必須設置 base_name

上面的例子會生成如下 URL 模式:框架

  • URL pattern: ^users/$ Name: 'user-list'
  • URL pattern: ^users/{pk}/$ Name: 'user-detail'
  • URL pattern: ^accounts/$ Name: 'account-list'
  • URL pattern: ^accounts/{pk}/$ Name: 'account-detail'

注意:base_name 參數用於指定視圖名稱模式的初始部分。在上面的例子中,是 useraccount 部分。ide

一般,您不須要指定 base_name 參數,可是若是您有一個視圖集定義了自定義 get_queryset 方法,那麼該視圖集可能沒有設置 .queryset 屬性。若是此時嘗試註冊該視圖,則會看到以下所示的錯誤:函數

'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
複製代碼

'base_name' 參數未指定,而且沒法自動肯定視圖中的名稱,由於它沒有' .queryset' 屬性。

這時候就須要在註冊視圖集時顯式設置 base_name 參數,由於它沒法從模型名稱中自動肯定。

使用 include 與路由

路由實例上的 .urls 屬性是一個標準的 URL patterns。關於如何包含這些 URL,有許多不一樣的樣式。

例如,能夠將 router.urls 附加到現有視圖的列表中...

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
]

urlpatterns += router.urls
複製代碼

另外,你也可使用 Django 的 include 函數,好比...

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^', include(router.urls)),
]
複製代碼

還能夠設置 namespace。

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include(router.urls, namespace='api')),
]
複製代碼

若是對超連接序列化器使用命名空間,則還須要確保序列化器上的任何 view_name 參數都能正確反映命名空間。在上面的示例中,您須要爲超連接到用戶詳細信息視圖的序列化程序字段包含諸如 view_name='api:user-detail' 之類的參數。

額外的連接和操做

@detail_route@list_route 裝飾的 視圖上的任何方法 也將被路由。例如,在 UserViewSet 類中給出這樣的方法:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):
    ...

 @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None):
        ...
複製代碼

會生成如下URL模式:

  • URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password'

若是您不想使用默認生成的 URL 模式,則可使用 url_path 參數對其進行自定義。

例如,若是您想將咱們的自定義操做的URL更改成 ^users/{pk}/change-password/$,則能夠編寫:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):
    ...

 @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password')
    def set_password(self, request, pk=None):
        ...
複製代碼

上面的例子如今將生成如下URL模式:

  • URL pattern: ^users/{pk}/change-password/$ Name: 'user-change-password'

若是您不想使用生成的默認名稱,則可使用 url_name 參數對其進行自定義。

例如,若是您想將自定義操做的名稱更改成 'user-change-password',則能夠編寫:

from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import detail_route

class UserViewSet(ModelViewSet):
    ...

 @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password')
    def set_password(self, request, pk=None):
        ...
複製代碼

上面的例子如今將生成如下URL模式:

  • URL pattern: ^users/{pk}/set_password/$ Name: 'user-change-password'

能夠同時使用 url_pathurl_name 參數。

更多相關信息請看 視圖集:標記額外的路由行爲

API 參考

SimpleRouter

SimpleRouter 包含標準的 listcreateretrieveupdatepartial_updatedestroy action。SimpleRouter 還支持視圖集使用 @detail_route@list_route 裝飾器標記其餘要路由的方法。

URL Style HTTP Method Action URL Name
{prefix}/ GET list {basename}-list
POST create
{prefix}/{methodname}/ GET, 或者由 `methods` 參數指定 `@list_route` 裝飾的方法 {basename}-{methodname}
{prefix}/{lookup}/ GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{methodname}/ GET, 或者由 `methods` 參數指定 `@detail_route` 裝飾的方法 {basename}-{methodname}

默認狀況下,由 SimpleRouter 建立的 URL 附加了尾部斜槓。在實例化路由器時,能夠經過將 trailing_slash 參數設置爲 False 來修改此行爲。例如:

router = SimpleRouter(trailing_slash=False)
複製代碼

尾部斜槓在 Django 中是常規的,但在其餘一些框架(如 Rails)中默認不使用。選擇使用哪一種風格在很大程度上是一個偏好問題,儘管一些 JavaScript 框架可能會指望特定的路由風格。

SimpleRouter 將匹配包含除斜槓和句點字符之外的任何字符的 lookup 值。對於更嚴格(或寬鬆)的 lookup pattern,請在視圖集上設置 lookup_value_regex 屬性。例如,您能夠將 lookup 限制爲有效的 UUID:

class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    lookup_field = 'my_model_id'
    lookup_value_regex = '[0-9a-f]{32}'
複製代碼

DefaultRouter

DefaultRouter 與上面的 SimpleRouter 類似,但還包含一個默認的 API 根視圖,該視圖返回一個包含指向全部列表視圖的超連接的響應。它還爲可選的 .json 風格格式後綴生成路由。

URL Style HTTP Method Action URL Name
[.format] GET 自動生成的根視圖 api-root
{prefix}/[.format] GET list {basename}-list
POST create
{prefix}/{methodname}/[.format] GET, 或者由 `methods` 參數指定 `@list_route` 裝飾的方法 {basename}-{methodname}
{prefix}/{lookup}/[.format] GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{methodname}/[.format] GET, 或者由 `methods` 參數指定 `@detail_route` 裝飾的方法 {basename}-{methodname}

注意:我在使用 3.7.7 版本時,發現要寫成 {prefix}[.format]/ 風格才能訪問,{prefix}/[.format] 風格會報 404,不知道是我設置問題仍是官方更新了。

SimpleRouter 同樣,經過在實例化 DefaultRouter 時將 trailing_slash 參數設置爲 False,能夠刪除 URL 路徑上的尾部斜槓。

router = DefaultRouter(trailing_slash=False)
複製代碼

自定義路由

自定義路由並非你常常須要作的事情,可是若是你對 API 的 URL 是如何構建的有特定的要求的話,它會頗有用。這樣作可讓你以可重用的方式封裝 URL 結構,確保你沒必要爲每一個新視圖明確編寫 URL 模式。

實現自定義路由的最簡單方法是對現有路由類之一進行子類化。.routes 屬性用於對將映射到每一個視圖集的 URL 模式進行模板化。.Routes 屬性是一個 Route 列表(Route 的是一個 namedtuple)。

Route 命名元組的參數:

url : 表示要路由的 URL 的字符串。能夠包含如下格式字符串:

  • {prefix} - 路由的 URL 前綴。
  • {lookup} - 匹配單個實例的 lookup field。
  • {trailing_slash} - 能夠是 '/' 或空字符串,具體取決於 trailing_slash 參數。

mapping : HTTP 方法名稱與視圖方法的映射

name: 用於調用 reverse 時的 URL 的名稱。可能包含如下格式字符串:

  • {basename} - 建立的 URL 名稱的基礎。

initkwargs: 實例化視圖時應傳遞的任何其餘參數的字典。注意,suffix 參數被保留用於標識視圖集類型,在生成視圖名稱和 breadcrumb 連接時使用。

自定義動態路由

你還能夠自定義 @list_route@detail_route 裝飾器的路由方式。要路由這兩個裝飾器中的一個或兩個,請在 .routes 列表中包含一個 DynamicListRoute 和/或 DynamicDetailRoute(別忘了類型是 namedtuple)。

DynamicListRouteDynamicDetailRoute 的參數是:

url: 表示要路由的 URL 的字符串。能夠包含與 Route 相同的格式字符串,而且還接受 {methodname}{methodnamehyphen} 格式的字符串。

name: 用於調用 reverse 時的名稱。能夠包含如下格式字符串:{basename} , {methodname}{methodnamehyphen}

initkwargs: 實例化視圖時應傳遞的任何其餘參數的字典。

舉個栗子

如下示例只會路由 listretrieve action,而且不使用尾部斜槓約定。

from rest_framework.routers import Route, DynamicDetailRoute, 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',
            initkwargs={'suffix': 'List'}
        ),
        Route(
            url=r'^{prefix}/{lookup}$',
            mapping={'get': 'retrieve'},
            name='{basename}-detail',
            initkwargs={'suffix': 'Detail'}
        ),
        DynamicDetailRoute(
            url=r'^{prefix}/{lookup}/{methodnamehyphen}$',
            name='{basename}-{methodnamehyphen}',
            initkwargs={}
        )
    ]
複製代碼

讓咱們來看看 CustomReadOnlyRouter 爲一個簡單的視圖集生成的路由。

views.py

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """ A viewset that provides the standard actions """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'username'

 @detail_route()
    def group_names(self, request, pk=None):
        """ Returns a list of all the group names that the given user belongs to. """
        user = self.get_object()
        groups = user.groups.all()
        return Response([group.name for group in groups])
複製代碼

urls.py

router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = router.urls
複製代碼

將生成如下映射...

URL HTTP Method Action URL Name
/users GET list user-list
/users/{username} GET retrieve user-detail
/users/{username}/group-names GET group_names user-group-names

有關設置 .routes 屬性的另外一個示例,請參閱 SimpleRouter 類的源代碼。

自定義路由器進階

若是想提供徹底自定義的行爲,能夠繼承 BaseRouter 並覆蓋 get_urls(self) 方法。該方法應檢查已註冊的視圖集並返回一組 URL 模式。能夠經過訪問 self.registry 屬性來檢查註冊的 prefix,viewset 和 basename tuples。

你可能還想覆蓋 get_default_base_name(self,viewset)方法,或者在向路由註冊視圖集時始終顯式設置 base_name 參數。

第三方軟件包

如下是可用的第三方包。

DRF Nested Routers

ModelRouter (wq.db.rest)

DRF-extensions

相關文章
相關標籤/搜索