資源路由允許你快速聲明給定的有足夠控制器的所有公共路由。而不是為你的index...聲明單獨(dú)的路由,一個(gè)強(qiáng)大的路由能在一行代碼中聲明它們?!?[Ruby on Rails 文檔][cite]
某些Web框架(如Rails)提供了自動(dòng)確定應(yīng)用程序的URL應(yīng)如何映射到處理傳入請(qǐng)求的邏輯的功能。
REST框架添加了對(duì)自動(dòng)URL路由到Django的支持,并為你提供了一種簡(jiǎn)單、快速和一致的方式來將視圖邏輯連接到一組URL。
這里有一個(gè)簡(jiǎn)單的URL conf的例子,它使用 SimpleRouter。
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
register() 方法有兩個(gè)強(qiáng)制參數(shù):
還可以指定一個(gè)附加參數(shù)(可選):
上面的示例將生成以下URL模式:
注意: base_name 參數(shù)用于指定視圖名稱模式的初始部分。在上面的例子中就是指 user 或 account 部分。
通常,你不需要指定base_name參數(shù),但是如果你有自定義get_queryset方法的視圖集,那么那個(gè)視圖集可能沒有設(shè)置.queryset屬性。當(dāng)你注冊(cè)這個(gè)視圖集的時(shí)候,你就有可能會(huì)看到類似如下的錯(cuò)誤:
'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
這意味著你需要在注冊(cè)視圖集時(shí)顯式設(shè)置base_name參數(shù),因?yàn)闊o法從model名自動(dòng)確定。
路由器實(shí)例上的.urls屬性只是一個(gè)URL模式的標(biāo)準(zhǔn)列表。對(duì)于如何添加這些URL,有很多不同的寫法。
例如,你可以將router.urls附加到現(xiàn)有視圖的列表中...
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函數(shù),像這樣...
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^', include(router.urls)),
]
路由器URL模式也支持命名空間的寫法。
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^api/', include(router.urls, namespace='api')),
]
如果使用帶超鏈接序列化器的命名空間,你還需要確保序列化器上的任何view_name參數(shù)正確地反映命名空間。在上面的示例中,你需要讓超鏈接到用戶詳細(xì)信息視圖的序列化器字段包含一個(gè)參數(shù),例如view_name ='api:user-detail'。
用@detail_route或@list_route裝飾的視圖集上的任何方法也將被路由。 例如,給定一個(gè)類似這樣的方法在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模式:
如果你不想讓自定義的操作使用自動(dòng)生成的默認(rèn)URL,你可以改用url_path參數(shù)進(jìn)行自定義。
例如,如果你要將自定義操作的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格式:
在你不想使用為自定義操作生成的默認(rèn)名稱的情況下,ni可以使用url_name參數(shù)來自定義它。
例如,如果要將自定義操作的名稱更改為'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):
...
以上示例現(xiàn)在將生成以下URL格式:
你還可以同時(shí)設(shè)置url_path和url_name參數(shù)對(duì)自定義視圖的URL生成進(jìn)行額外的控制。
有關(guān)更多信息,請(qǐng)參閱viewset文檔 [標(biāo)記路由的額外操作][route-decorators].
該路由器包括標(biāo)準(zhǔn)集合list, create, retrieve, update, partial_update 和 destroy動(dòng)作的路由。視圖集中還可以使用@ detail_route或@ list_route裝飾器標(biāo)記要被路由的其他方法。
URL 樣式 | HTTP 方法 | 動(dòng)作 | URL 名 |
---|---|---|---|
{prefix}/ | GET | list | {basename}-list |
POST | create | ||
{prefix}/{methodname}/ | GET, or as specified by `methods` argument | `@list_route` decorated method | {basename}-{methodname} |
{prefix}/{lookup}/ | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/ | GET, or as specified by `methods` argument | `@detail_route` decorated method | {basename}-{methodname} |
默認(rèn)情況下,由SimpleRouter創(chuàng)建的URL將附加尾部斜杠。 在實(shí)例化路由器時(shí),可以通過將trailing_slash參數(shù)設(shè)置為`False'來修改此行為。比如:
router = SimpleRouter(trailing_slash=False)
尾部斜杠在Django中是常見的,但是在其他一些框架(如Rails)中默認(rèn)不使用。你選擇使用哪種風(fēng)格在很大程度上是你個(gè)人偏好問題,雖然一些javascript框架可能需要一個(gè)特定的路由風(fēng)格。
路由器將匹配包含除斜杠和句點(diǎn)字符以外的任何字符的查找值。對(duì)于更嚴(yán)格(或更寬松)的查找模式,請(qǐng)?jiān)谝晥D集上設(shè)置lookup_value_regex屬性。例如,你可以將查找限制為有效的UUID:
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
這個(gè)路由器類似于上面的SimpleRouter,但是還包括一個(gè)默認(rèn)返回所有列表視圖的超鏈接的API根視圖。它還生成可選的.json樣式格式后綴的路由。
URL 樣式 | HTTP 方法 | 動(dòng)作 | URL 名稱 |
---|---|---|---|
[.format] | GET | automatically generated root view | api-root |
{prefix}/[.format] | GET | list | {basename}-list |
POST | create | ||
{prefix}/{methodname}/[.format] | GET, or as specified by `methods` argument | `@list_route` decorated method | {basename}-{methodname} |
{prefix}/{lookup}/[.format] | GET | retrieve | {basename}-detail |
PUT | update | ||
PATCH | partial_update | ||
DELETE | destroy | ||
{prefix}/{lookup}/{methodname}/[.format] | GET, or as specified by `methods` argument | `@detail_route` decorated method | {basename}-{methodname} |
與SimpleRouter一樣,在實(shí)例化路由器時(shí),可以通過將trailing_slash參數(shù)設(shè)置為`False'來刪除URL路由的尾部斜杠。
router = DefaultRouter(trailing_slash=False)
通常你并不需要實(shí)現(xiàn)自定義路由器,但如果你對(duì)API的網(wǎng)址結(jié)構(gòu)有特定的要求,那它就十分有用了。這樣做允許你以可重用的方式封裝URL結(jié)構(gòu),確保你不必為每個(gè)新視圖顯式地編寫URL模式。
實(shí)現(xiàn)自定義路由器的最簡(jiǎn)單的方法是繼承一個(gè)現(xiàn)有的路由器類。.routes屬性用于模板將被映射到每個(gè)視圖集的URL模式。.routes屬性是一個(gè)名為tuples的Route對(duì)象的列表。
Route命名元組的參數(shù)是:
url: 表示要路由的URL的字符串??赡馨ㄒ韵赂袷阶址?/p>
mapping: HTTP方法名稱到視圖方法的映射
name: 在reverse調(diào)用中使用的URL的名稱??赡馨ㄒ韵赂袷阶址?/p>
initkwargs: 實(shí)例化視圖時(shí)應(yīng)傳遞的任何其他參數(shù)的字典。注意,suffix參數(shù)被保留用于標(biāo)識(shí)視圖集類型,在生成視圖名稱和面包屑鏈接時(shí)使用。
你還可以定制@ list_route和@detail_route裝飾器的路由。要路由這些裝飾器中的一個(gè)或兩個(gè),請(qǐng)?jiān)?routes列表中包含一個(gè)DynamicListRoute和/或DynamicDetailRoute命名的元組。
DynamicListRoute和DynamicDetailRoute的參數(shù)是:
url: 表示要路由的URL的字符串。可以包括與“Route”相同的格式字符串,并且另外接受{methodname}和{methodnamehyphen}格式字符串。
name: 在reverse調(diào)用中使用的URL的名稱??赡馨ㄒ韵赂袷阶址簕basename},{methodname}和{methodnamehyphen}。
initkwargs: 實(shí)例化視圖時(shí)應(yīng)傳遞的任何其他參數(shù)的字典。
以下示例將只路由到list和retrieve操作,并且不使用尾部斜線約定。
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為簡(jiǎn)單視圖生成的路由。
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):
"""
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 方法 | 動(dòng)作 | URL 名稱 |
---|---|---|---|
/users | GET | list | user-list |
/users/{username} | GET | retrieve | user-detail |
/users/{username}/group-names | GET | group_names | user-group-names |
更多建議: