rest-framework routers

路由器

资源路由可以让你快速声明所有给定的足智多谋的控制器的共同路线。相反,宣布独立的路线索引的......一个足智多谋的路线宣称他们在一个单一的代码行。

- Ruby on Rails的文档

一些Web框架如Rails的用于自动地确定如何为应用程序的URL应该被映射到所述逻辑提供功能与处理传入请求的交易。

REST框架增加了对自动URL路由Django的支持,并为您提供您的接线鉴于逻辑URL集的简单,快速,一致的方式。

用法

这里有一个简单的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()方法:

  • prefix - URL前缀用于此路由集合。
  • viewset - 该视图集类。

另外,您还可以指定一个额外的参数:

  • basename-该基地用于所创建的URL名称。如果未设置基本名称将根据自动生成queryset的视图集的属性,如果它有一个。请注意,如果视图集不包括queryset属性,则必须将basename注册视图集时。

上面的例子将产生下面的URL模式:

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

注意:该basename参数用于指定视图名称模式的起始部分。在上面的例子,这就是useraccount部分。

通常你不会需要到指定basename的说法,但如果你有,你已经定义了一个自定义的一个视图集get_queryset方法,那么视图集可能没有一个.queryset属性集。如果试图注册该视图集中你会看到这样的错误:

'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.

这意味着你需要明确地设置basename注册视图集的时候,因为它不能自动从型号名称确定的说法。


使用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/$', ForgotPasswordFormView.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')),
]

见Django的URL命名空间文档includeAPI参考的更多细节。


注意:如果使用带您还需要确保任何超链接串行命名空间view_name上的串行参数正确反映命名空间。在上面的例子中你需要包括参数,如 view_name='app_name:user-detail'用于超链接到用户细节视图串行字段。

自动view_name生成使用像的图案%(model_name)-detail。除非你的模型名称冲突实际上你可能会更好使用超链接的串行时命名空间Django的REST框架意见。


路由额外行动

一个视图集可用于路由标记额外的操作通过装饰用的方法@action装饰。这些额外的措施将包括在生成的路线。例如,给定的set_password上所述方法UserViewSet类:

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

class UserViewSet(ModelViewSet):
    ...

    @action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf])
    def set_password(self, request, pk=None):
        ...

下面的路由将产生:

  • URL模式: ^users/{pk}/set_password/$
  • 网址名称: 'user-set-password'

默认情况下,URL模式是基于方法名和URL名称是的组合ViewSet.basename和复姓方法名。如果你不想使用默认设置这些值,可以代替提供url_pathurl_name参数的@action装饰。

例如,如果你想改变我们的自定义操作的网址^users/{pk}/change-password/$,你可以写:

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

class UserViewSet(ModelViewSet):
    ...

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

上面的例子,现在会生成以下URL模式:

  • URL路径: ^users/{pk}/change-password/$
  • 网址名称: 'user-change_password'

API指南

SimpleRouter

该路由器包括一套标准的途径listcreateretrieveupdatepartial_updatedestroy行动。该视图集中还可以标记其他方法来进行路由,使用@action装饰。

URL风格 HTTP方法 行动 URL名称
{字首}/ 得到 名单 {}基本名-list
POST 创建
{前缀} / {url_path} / GET,或由methods参数指定 @Action(详细=假)装饰方法 {}基名 - {} URL_NAME
{前缀} / {查找} / 得到 取回 {}基本名-detail
更新
补丁 partial_update
删除 破坏
{前缀} / {查找} / {url_path} / GET,或由methods参数指定 @Action(详细=真)装饰方法 {}基名 - {} URL_NAME

默认情况下,通过建立的网址SimpleRouter被附加以斜杠。这种行为可以通过设置来修改trailing_slash参数来False实例化路由器时。例如:

router = SimpleRouter(trailing_slash=False)

结尾的斜杠在Django常规的,但在某些其他框架如导轨不使用缺省值。您选用的风格在很大程度上是偏好的问题,但也有一些JavaScript框架可以期待一个特定的路由风格。

路由器将匹配查找含有除斜线和周期字符的任何字符的值。对于更严格的(或宽松)查找图案,设置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风格 HTTP方法 行动 URL名称
[。格式] 得到 自动生成的根查看 火根
{前缀} / [格式] 得到 名单 {}基本名-list
POST 创建
{前缀} / {url_path} / [格式] GET,或由methods参数指定 @Action(详细=假)装饰方法 {}基名 - {} URL_NAME
{前缀} / {查找} / [格式] 得到 取回 {}基本名-detail
更新
补丁 partial_update
删除 破坏
{前缀} / {查找} / {url_path} / [格式] GET,或由methods参数指定 @Action(详细=真)装饰方法 {}基名 - {} URL_NAME

正如SimpleRouter在URL路径后斜线可以通过设置除去trailing_slash参数False实例路由器时。

router = DefaultRouter(trailing_slash=False)

定制路由器

实现自定义路由器是不是你需要经常做的,但如果你有关于如何为你的API的网址是结构化的具体要求也可以是有用的。这样做可以让你封装URL结构,确保你没有明确地写你的URL模式为每个新视图可重复使用的方式。

实现自定义路由器最简单的方法是继承现有的路由器类之一。该.routes属性用于模板将被映射到每个视图集的URL的模式。该.routes属性是一个列表Route命名的元组。

到的参数Route命名为元组是:

URL被路由代表URL的字符串。可以包括以下格式的字符串:

  • {prefix} - URL前缀用于此路由集合。
  • {lookup} - 查找字段用于匹配的单个实例。
  • {trailing_slash}-无论是“/”或空字符串,这取决于trailing_slash参数。

映射:HTTP方法名的映射到视图的方法

名称:URL的名称中使用reverse电话。可以包括以下格式的字符串:

  • {basename} - 该基地用于所创建的URL名称。

initkwargs:的应实例视图时被传递任何额外的参数的字典。请注意,detailbasename,和suffix参数保留给视图集中内省和也使用可浏览的API生成视图名称和面包屑链接。

自定义动态路由

您还可以自定义如何@action装饰路由。包括DynamicRoute在指定的元组.routes列表,设置detail参数为适用于基于明细清单为基础和路线。此外detail,该参数DynamicRoute是:

URL被路由代表URL的字符串。可包括相同的格式字符串作为Route,另外接受{url_path}格式字符串。

名称:URL的名称中使用reverse电话。可以包括以下格式的字符串:

  • {basename} - 该基地用于所创建的URL名称。
  • {url_name}-在url_name所提供的@action

initkwargs:的应实例视图时被传递任何额外的参数的字典。

下面的例子将只对路线listretrieve行动,并且不使用尾部斜杠约定。

from rest_framework.routers import Route, DynamicRoute, 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',
            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={}
        )
    ]

让我们来看看我们的路线CustomReadOnlyRouter会产生一个简单的视图集。

views.py:

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

    @action(detail=True)
    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

下面的映射将产生...

网址 HTTP方法 行动 URL名称
/用户 得到 名单 用户列表
/用户/ 得到 取回 用户细节
/用户/ {名} / GROUP_NAMES 得到 GROUP_NAMES 用户组名

用于设置的其他例子.routes的属性,请参阅所述的源代码SimpleRouter的类。

高级定制路由器

如果你想提供完全定制的行为,则可以覆盖BaseRouter和重写get_urls(self)方法。该方法应检查注册viewsets和返回的URL模式列表。注册的前缀,视图集和基本名称元组可以通过访问进行检查self.registry属性。

您可能还需要重写get_default_basename(self, viewset)方法,否则始终明确设置basename与路由器注册您的viewsets时的说法。

第三方软件包

下面的第三方软件包也可提供。

DRF嵌套路由器

DRF-嵌套的路由器包提供路由器和关系字段用于与嵌套资源工作。

型号路由器(wq.db.rest)

所述wq.db包提供了一个先进ModelRouter延伸类(和单个实例)DefaultRouterregister_model()的API。就像Django的admin.site.register,唯一需要的参数rest.router.register_model是一个模型类。一个URL前缀,串行和视图集中合理的默认值会从模型和全局配置中推断出来。

from wq.db import rest
from myapp.models import MyModel

rest.router.register_model(MyModel)

DRF-扩展

DRF-extensions软件包提供了路由器创建嵌套viewsets收藏级控制器定制的端点名

posted @ 2020-03-12 15:12  pythonliuwei  阅读(465)  评论(0编辑  收藏  举报