REST framework增加可对Django自动URL路由的支持,并提供了一种简单、快速和一致的方式,将视图逻辑编辑到一组URL。

用法

SimpleRouter的URLconf示例

from rest_framework import routers


router = routers.SimpleRouter()
router.register(r"users", UserViewSet)
router.register(r"accounts", AccountViewSet)
urlpatterns = router.urls

register必填参数:

  • prefix:用于此路由集的URL前缀。
  • viewset:视图集类。

register附加参数:

  • base_name:用于创建的URL名称的基础。如果未设置,basename将根据视图集的queryset属性自动生成。注意,如果视图集不包含queryset属性,那么在注册视图集时必须设置base_name。

上面的示例将生成以下URL模式:

  • URL模式:^users/$,名称:user-list
  • URL模式:^users/{pk}/$,名称:user-detail
  • URL模式:^accounts/$,名称:account-list
  • URL模型:^accounts/{pk}/$,名称:account-detail

注意:base_name参数用于指定视图名称模式的初始部分。在上面是示例中,是user和account部分。
通常,不需要指定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.

使用路由器的include

路由器实例上的.urls属性仅仅是URL模式的标准列表。关于如何包含这些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/$', ForgotPassworkFormView.as_view()),
    url(r'^', include(router.urls)),
]

可以在应用程序命名空间中使用include

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include((router.urls, 'app_name'))),
]

或应用程序和实例命名空间

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

注意:如果对超链接序列化器使用命名空间,则还需要确保序列化器上的任何view_name参数都能正确反映命名空间。在上面的示例中,需要为超链接到用户详细视图的序列化字段包含一个诸如view_name='api:user-detail'之类的参数。
使用类似%(model-name)-detail模式自动生成view_name。除非模型名称实际上发生冲突,否则在使用超链接序列化器时,最好不要对Django REST framework视图进行命名。

额外操作的路由

视图集可以通过使用@action装饰器方法来标记路由的额外操作。这些额外的操作将包含在省城的路由中。
示例:

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


class UserViewSet(ModelViewSet):
    ...
    @action(method=["post"], detail=True, permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None)

将生成以下路由:

  • URL模式:^users/{pk}/set_password/$
  • URL名称:'user-set-password'
    默认情况下,URL模式基于方法名,URL名称是ViewSet.basename和带连字符的方法名称的组合。如果不想使用这些值中的任何一个默认值,可以向@action装饰器提供url_pathurl_name参数。
    示例:
    ```python
    from rest_framework.decorators import action
    from myapp.permissions import IsAdminOrIsSelf

class UserViewSet(ModelViewSet):

@action(methods=[“post”], detail=True, pemission_classes=[IsAdminOrIsSelf], url_path=”change-password”, url_name=”change_password”)
def set_password(self, request, pk=None):

上面的示例现在将生成以下URL模式:
- URL路径:`^users/{pk}/change-password/$`
- URL名称:`'user-change_password'`

### API指南
#### SimpleRouter
此路由器包含标准的list, create, retrieve, update, partial_update和destroy操作的路由。视图集还可以使用`@action`装饰器标记被路由的其他方法。

|URL Style|HTTP Method| Action  | URL Name  |
| ------------ | ------------ | ------------ | ------------ |
| {prefix}/  | GET  | list  | {basename}-list  |
| {prefix}/  | POST  | create  | {basename}-list  |
| {prefix}/{url_path}/  | GET或有方法参数指定  | `@action(detail=False)`装饰器  | {basename}-{url_name}  |
| {prefix}/{lookup}/  | GET  | retrieve  | {basename}-detail  |
| {prefix}/{lookup}/  | PUT  | update  | {basename}-detail  |
| {prefix}/{lookup}/  | PATCH  | partial_update  | {basename}-detail  |
| {prefix}/{lookup}/  | DELETE  | destroy  | {basename}-detail  |
| {prefix}/{lookup}/{url_path}/  | GET或有方法参数指定  | `@action(detail=True)`装饰器  | {basename}-{url_name}  |
默认情况下,SimpleRouter创建的URL附加了一个尾部斜杠,在实例化路由器时,可以通过trailing_slash参数设置为False来修改此行为。
```python
router = SimpleRouter(trailing_slash=False)

在Django中,尾部斜杆是常规的,但在某些其他框架中默认不使用。
路由器将匹配包含除斜杠和句点字符以外的任何字符的查找值。对于更严格(或宽松)的查找模式,请在视图集上设置lookup_value_regex属性。例如,可以将查找限制为有效的UUID:

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

DefaultRouter

此路由器与SimpleRouter类似。但另外包括一个默认的API根视图,它返回包含所有列表视图的超链接的相应。它还为可选的.json样式格式后缀生成路由器。

URL Style HTTP Method Action URL Name
[.format] GET 自动生成的根视图 api-root
{prefix}/[.format] GET list {basename}-list
{prefix}/[.format] POST create {basename}-list
{prefix}/{url_path}/[.format] GET或有方法参数指定 @action(detail=False)装饰器 {basename}-{url_name}
{prefix}/{lookup}/[.format] GET retrieve {basename}-detail
{prefix}/{lookup}/[.format] PUT update {basename}-detail
{prefix}/{lookup}/[.format] PATCH partial_update {basename}-detail
{prefix}/{lookup}/[.format] DELETE destroy {basename}-detail
{prefix}/{lookup}/{url_path}/[.format] GET或有方法参数指定 @action(detail=True)装饰器 {basename}-{url_name}

与SimpleRouter一样,在实例化路由器时通过将trailing_slash参数设置为False来删除URL路由上的尾部斜杠。

router = DefaultRouter(trailing_slash=False)

自定义路由器

实现自定义路由器不是经常需要做的事情,但是如果对API的URL如何构造有特定的要求,它会很有用。这样做允许以可重用的方式封装URL结构,以确保不必为每个新视图编写URL模式。
实现自定义路由的最简单方法是对现有路由器之一进行子类化。.routes属性用于对将映射到每个视图集的URL模式进行模板化。.routes属性是Route元组表。
Route命名元组的参数:
url:表示被路由的URL的字符串。可能包含以下格式的字符串:

  • {perfix}:用于这组路由的URL前缀。
  • {lookup}:用于匹配单个实例的查找字段。
  • {trailing_slash}:”/“或空字符串,取决于trailing_slash参数。

mapping:HTTP方法名称到视图方法的映射。
name:在reverse调用时使用的URL名称。可能包含以下格式字符串:

  • {basename}:用于创建的URL名称的基础。
    initkwargs:实例化视图时传递的任何其他参数的字典。注意,detail,basename和suffix参数是视图集内省保留的,并也可由可浏览API使用来生成视图名称和痕迹连接。

自定义动态路由

还有自定义@action装饰器的路由方式。在.routes列表中包含名为tuple的DynamicRoute,将detail参数设置为适合基于列表和基于详细信息的路由。除了detail之外,DynamicRoute的参数是:
url:表示被路由的URL的字符串。可以包含与Route相同的格式字符串,并额外接受{url_path}格式字符串。
name:在reverse调用时使用的URL名称。可能包含以下格式字符串:

  • {basename}:用于创建的URL名称的基础。
  • {url_name}:提供给@action的url_name。
    initkwargs:实例化视图时传递的任何其他参数的字典。

    示例

    下面的实例将只路由list和retrieve操作,不使用斜杠约定。
    ```python
    from rest_framework.routers import Router, DynamicRouter, SimpleRouter

class CustomReadOnlyRouter(SimpleRouter):
“””
用于只读API的路由器,不使用尾部斜杠
“””
routes = [
Route(
url=r’^{prefix}$’,
mapping={“get”: “list”},
name=”{basename}-list”,
detail=False,
initkwargs={“suffix”: “List”}
),
Route(
url=r’^{prefix}/{lookup}$’,
mapping={“get”: “retrieve”},
name=”{basename}-detail”,
detail=True,
initkwargs={“suffix”: “Detail”}
),
DynamicRoute(
url=r’^{prefix}/{lookup}/{url_path}$’,
name=”{basename}-{url_name}}”,
detail=True,
initkwargs={}
)
]

views.py
```python
class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    提供标准操作的视图集
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = "username"

    @action(detail=True)
    def group_names(self, request, pk=None):
    """
    返回给定用户所属的所有组名称和列表
    """
        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

高级定制路由器

如果想提供整个自定义的行为,可以重写BaseRouter并重写get_urls(self)方法。该方法检查一注册的视图集并返回URL模式列表。可以通过访问self.registry属性来检查已注册的preifx,viewsets和basename tuple。
可能还希望重写get_default_basen

0条评论

相关推荐

django教程

r

Django 2019-05-20 10:53:53

Celery

celery学习资料

Django 2019-05-25 18:41:55

django教程入门

适合django新人使用的学习手册

Django 2019-07-01 14:28:04

django实用资料

django项目从0到1自己总结的实用的资料,大部分常用的功能这里都有

Django 2019-05-08 18:21:34