DRF之路由组件

五】路由组件

资源路由允许你快速声明给定的有足够控制器的所有公共路由。而不是为你的index...声明单独的路由,一个强大的路由能在一行代码中声明它们。

— Ruby on Rails 文档

【1】使用SimpleRouter快速生成路由

from .views import TaskViewV3
# 导入模块
from rest_framework.routers import SimpleRouter
from django.urls import path, include

# 实例化得到对象
router = SimpleRouter()
# 执行对象的register方法
router.register(prefix='task', viewset=TaskViewV3, basename='task')


urlpatterns = [
    # 获取对象的urls属性
    path('v1/', include(router.urls))
]

image-20240422224608500

【1.1】参数

  • register() 方法有两个强制参数:

    • prefix - 用于此组路由的URL前缀。

    • viewset - 处理请求的viewset类。

  • 还可以指定一个附加参数(可选):

    • base_name - 用于创建的URL名称的基本名称。
    • 如果不设置该参数,将根据视图集的queryset属性(如果有)来自动生成基本名称。
    • 注意,如果视图集不包括queryset属性,那么在注册视图集时必须设置base_name

【1.2】在路由中将快速生成的路由添加到urlpatterns的多种方式

  • 路由器实例上的.urls属性只是一个URL模式的标准列表。对于如何添加这些URL,有很多不同的写法
【1.2.1】将router.urls附加到现有视图的列表中 urlpatterns += router.urls
urlpatterns = [
    path('',根路由)
]

urlpatterns += router.urls
【1.2.2】使用Django的include函数
urlpatterns = [
    path('v1/', include(router.urls))
]

【2】SimpleRouter

  • 该路由器包括标准集合list, create, retrieve, update, partial_updatedestroy动作的路由。
  • 视图集中还可以使用@ detail_route@ list_route装饰器标记要被路由的其他方法。

image-20240422223309809

  • 默认情况下,由SimpleRouter创建的URL将附加尾部斜杠。 在实例化路由器时,可以通过将trailing_slash参数设置为`False'来修改此行为。

    • router = SimpleRouter(trailing_slash=False)
  • 路由器将匹配包含除斜杠和句点字符以外的任何字符的查找值。

  • 对于更严格(或更宽松)的查找模式,请在视图集上设置lookup_value_regex属性。

    • 例如,你可以将查找限制为有效的UUID:
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    lookup_field = 'my_model_id'
    lookup_value_regex = '[0-9a-f]{32}'

【3】DefaultRouter

  • 这个路由器类似于上面的SimpleRouter,但是还包括一个默认返回所有列表视图的超链接的API根视图。它还生成可选的.json样式格式后缀的路由。

image-20240422225751808

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

image-20240422225856053

  • 上述是访问路由根路径时,使用DefaultRouter将会自动生成根路径的页面,如果使用SimpleRouter将会报错

【4】action装饰器

from rest_framework.decorators import action
  • @action装饰器函数是Django REST Framework中用于定义自定义动作的一种方法。
  • 它可以让你在视图集中添加额外的自定义动作,并将它们映射到特定的HTTP方法和URL路径上。

【4.1】使用场景

@action装饰器的使用场景包括但不限于以下几种情况:

  1. 自定义操作:当你需要在视图集中添加一些不属于标准CRUD操作(创建、读取、更新、删除)的自定义操作时,可以使用@action装饰器。例如,向用户发送邮件、将资源标记为喜欢或收藏等。
  2. 扩展标准操作:有时,标准的CRUD操作可能不足以满足你的需求,你可能需要为某些资源添加额外的操作。使用@action装饰器可以轻松地在视图集中添加这些自定义操作。
  3. 复杂业务逻辑:某些操作可能涉及到复杂的业务逻辑,无法简单地通过标准的CRUD操作来实现。在这种情况下,你可以使用@action装饰器来定义并实现这些操作。
  4. 对单个实例或整个集合的操作:通过detail参数,你可以指定自定义操作是针对单个实例还是整个集合的。这样可以灵活地定义不同类型的操作。
  5. 扩展API的功能:使用@action装饰器可以轻松地扩展API的功能,使其更加灵活和强大,从而满足不同场景下的需求。

【4.2】使用

  • action(methods=None, detail=None, url_path=None, url_name=None, **kwargs)

源码说明:

将一个ViewSet方法标记为可路由的动作。

@action装饰的函数将被赋予一个mapping属性,一个MethodMapper,可以用来在路由动作上添加额外的基于方法的行为。

  • 参数说明
    • methods:一个列表,表示此动作响应的HTTP方法名称。默认为仅接受GET请求。
    • detail:必填项。确定此动作是应用于实例/详情请求还是集合/列表请求。
    • url_path:定义此动作的URL片段。默认为被装饰方法的名称。
    • url_name:定义此动作的内部(reverse)URL名称。默认为被装饰方法的名称,其中下划线被连字符替换。
    • kwargs:用于在视图上设置其他属性。这可用于覆盖视图集级别的*_classes设置,类似于函数式API视图中的@renderer_classes等装饰器的工作原理

【4.3】使用案例(自动生成路由)

  • 当您使用自动生成的路由时,Django REST Framework会自动检测装饰有@action的方法,并将其转换为相应的URL路径。
  • 这是因为@action装饰器会影响ViewSet中的路由配置,并告诉框架应该将这些自定义操作公开为API端点。
# views.py
class TaskViewV3(GenericViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSer

    @action(methods=['POST'], detail=False)
    def login(self, request):
        '''登录代码逻辑'''
        return Response('xxx')

    @action(methods=['POST'], detail=False)
    def register(self, request):
        '''注册代码逻辑'''
        return Response('xxx')

    @action(methods=['PUT', 'DELETE', 'PATCH'], detail=False)
    def other(self, request, *args, **kwargs):
        '''其他请求方式的操作逻辑'''
        return Response('xxx')
# urls.py
from .views import TaskViewV3
from rest_framework.routers import SimpleRouter
from django.urls import path, include

router = SimpleRouter()
router.register(prefix='task', viewset=TaskViewV3, basename='task')
urlpatterns = [
    path('v1/', include(router.urls))
]

image-20240425152938990

image-20240425153151417

【4.3.1】使用自动生成路由 + action的url_path参数 实现自定义路径
# views.py
class CommonView(ViewSet):

    @action(methods=['get'], detail=False, url_path='xxx', url_name='xxx')
    def xxx(self, request):
        return Response('xxx')

    @action(methods=['post'], detail=False, url_path='abc', url_name='abc')
    def abc(self, request):
        return Response('abc')
# urls.py
router = SimpleRouter()
router.register(prefix='router', viewset=CommonView, basename='common')
urlpatterns = [
	# 此处留空
]
urlpatterns += router.urls

image-20240425160914787

【4.4】使用案例2(不使用自动生成路由的情况下使用aciton装饰器)

  • @action 装饰器的作用在于为自动生成路由的情况下提供便利。但即使在手动定义路由的情况下,@action 装饰器仍然有几个作用:
    1. 提供附加的元数据: 使用 @action 装饰器可以为自定义操作提供附加的元数据,例如 detail 参数用于指定操作是针对单个对象还是整个集合的。
    2. 提高可读性: 在视图类中使用 @action 装饰器标记自定义操作,可以使代码更具可读性和清晰度,因为它明确指示了这是一个自定义操作。
    3. 集中定义自定义操作: 使用 @action 装饰器将自定义操作直接与视图类关联,使得在代码中更容易找到和理解视图类的功能。
# urls.py
from .views import CommonView
from django.urls import path

urlpatterns = [
    path('no_router/', CommonView.as_view(actions={'get': 'xxx', 'post': 'abc'}))
]
class CommonView(ViewSet):

    @action(methods=['get'], detail=False)
    def xxx(self, request):
        return Response('xxx')

    @action(methods=['post'], detail=False)
    def abc(self, request):
        return Response('abc')

自动生成路由很方便,建议使用自动生成

posted @ 2024-04-25 16:12  Lea4ning  阅读(17)  评论(0编辑  收藏  举报