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))
]
【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_update
和destroy
动作的路由。 - 视图集中还可以使用
@ detail_route
或@ list_route
装饰器标记要被路由的其他方法。
-
默认情况下,由
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
样式格式后缀的路由。
- 与
SimpleRouter
一样,在实例化路由器时,可以通过将trailing_slash
参数设置为False
来删除URL路由的尾部斜杠
- 上述是访问路由根路径时,使用DefaultRouter将会自动生成根路径的页面,如果使用SimpleRouter将会报错
【4】action装饰器
from rest_framework.decorators import action
@action
装饰器函数是Django REST Framework中用于定义自定义动作的一种方法。- 它可以让你在视图集中添加额外的自定义动作,并将它们映射到特定的HTTP方法和URL路径上。
【4.1】使用场景
@action
装饰器的使用场景包括但不限于以下几种情况:
- 自定义操作:当你需要在视图集中添加一些不属于标准CRUD操作(创建、读取、更新、删除)的自定义操作时,可以使用
@action
装饰器。例如,向用户发送邮件、将资源标记为喜欢或收藏等。 - 扩展标准操作:有时,标准的CRUD操作可能不足以满足你的需求,你可能需要为某些资源添加额外的操作。使用
@action
装饰器可以轻松地在视图集中添加这些自定义操作。 - 复杂业务逻辑:某些操作可能涉及到复杂的业务逻辑,无法简单地通过标准的CRUD操作来实现。在这种情况下,你可以使用
@action
装饰器来定义并实现这些操作。 - 对单个实例或整个集合的操作:通过
detail
参数,你可以指定自定义操作是针对单个实例还是整个集合的。这样可以灵活地定义不同类型的操作。 - 扩展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))
]
【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
【4.4】使用案例2(不使用自动生成路由的情况下使用aciton装饰器)
@action
装饰器的作用在于为自动生成路由的情况下提供便利。但即使在手动定义路由的情况下,@action
装饰器仍然有几个作用:- 提供附加的元数据: 使用
@action
装饰器可以为自定义操作提供附加的元数据,例如detail
参数用于指定操作是针对单个对象还是整个集合的。 - 提高可读性: 在视图类中使用
@action
装饰器标记自定义操作,可以使代码更具可读性和清晰度,因为它明确指示了这是一个自定义操作。 - 集中定义自定义操作: 使用
@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')
自动生成路由很方便,建议使用自动生成