路由层
【1】原始路由
(1)正则re_path
from django.urls import path, re_path
from book import views
urlpatterns = [
re_path(r'book/(?P<pk>\d+)?/?$', views.BookAPIView.as_view(), name='book')
]
-
示例解释
-
(?P<pk>\d+)
是一个命名正则表达式组,它匹配一个或多个数字,并将匹配到的数字作为pk
参数传递给视图函数或视图类。 -
问号
?
表示这个部分是可选的,所以URL可以是book/
或book/123/
。
-
(2)路径转换器
- 简单介绍:
- int:捕获一个整数。
- str:捕获一个字符串,直到遇到下一个斜杠为止。
- slug:捕获一个由 ASCII 字母、数字、连字符或下划线组成的字符串。
- uuid:捕获一个 UUID。
- path:捕获整个 URL 路径片段,包括斜杠。
from django.urls import path
from book import views
urlpatterns = [
path('book/', views.BookAPIView.as_view(), name='book'),
path('book/<int:pk>/', views.BookOneAPIView.as_view(), name='bookOne'),
]
- 示例解释
<int:pk>
是一个路径转换器,它匹配一个整数,并将这个整数作为pk
参数传递给视图函数或视图类。- 这种写法比使用正则表达式更清晰、更易读。
【2】drf路由写法
(1)手写actions
- 在视图集中,只要继承了
ViewSetMixin
,那么就都需要在as_view
中传递参数actions
from book.views import BookViewSet
from django.urls import path, include
urlpatterns = [
path('book/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'})),
path('book/<int:pk>/', views.BookAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
- 在上面的例子中,
BookAPIView
是一个继承自ViewSetMixin
的视图类。 - 通过调用
as_view()
方法并传入一个字典,可以指定每个HTTP方法应该调用的视图集中的哪个动作。- 例如,
{'get': 'list', 'post': 'create'}
表示当使用GET方法访问/book/
路径时,将调用BookAPIView
中的list
动作;当使用POST方法时,将调用create
动作。
- 例如,
(2)自动生成router
- 自动生成router的方式通过使用DRF提供的路由器(如
DefaultRouter
或SimpleRouter
),可以大大简化URL的配置过程。 - 示例:针对上面同样的情况使用
SimpleRouter
from rest_framework.routers import SimpleRouter
from book.views import BookViewSet
from django.urls import path, include
router = SimpleRouter()
router.register(prefix='book', viewset=UserAPIView, basename='book')
urlpatterns += router.urls
- 参数讲解
prefix
:用于设置生成 URL 的前缀。viewset
:视图集(ViewSet
)的实例或者类,应该继承自rest_framework.viewsets.ViewSet
或其子类(如ModelViewSet
)basename
:用于生成 URL 名称,在反向解析 URL 时会用到。
(3)加入到路由的两种方式
urlpatterns += router.urls
- 将路由器生成的URL列表直接追加到现有的
urlpatterns
列表中。 - 这通常在你已经有了一些手动定义的URL模式,并且想要将路由器生成的URL模式追加到它们之后时使用。
- 将路由器生成的URL列表直接追加到现有的
path("", include(router.urls))
- 将路由器生成的URL模式包含在一个特定的路径下。
- 想要将一组相关的API端点组织在一个共同的URL前缀下时非常有用。只需要在path的第一个参数中添加前缀就可以
(4)SimpleRouter
和DefaultRouter
-
相同点:
- 自动生成URL:两者都能根据视图集中的方法自动生成对应的URL模式,无需手动编写每个URL。
- 提供视图集注册:通过
router.register()
方法,可以将视图集注册到路由器上,从而生成对应的URL。
-
不同点:
-
根视图和API界面
DefaultRouter
:除了为视图集中的每个操作生成URL之外,还会提供一个自动生成的API根视图和可浏览的API界面。这使得开发者可以更容易地查看和测试API。SimpleRouter
:只生成与视图集操作对应的URL,不提供自动生成的API根视图和可浏览的API界面。
-
路由URL数量
- 由于
DefaultRouter
提供了额外的根视图和API界面,因此生成的URL数量会比SimpleRouter
多。
- 由于
-
使用场景
DefaultRouter
:适用于需要提供一个完整且可浏览的API界面的场景,如开发API供外部调用或内部调试。SimpleRouter
:适用于只需要基本的URL映射,而不需要额外API界面的场景,或者当开发者希望减少生成的URL数量以提高性能时。
-
-
路径不同
print(router.urls)
# SimpleRouter
# [<URLPattern '^book/$' [name='book-list']>, <URLPattern '^book/(?P<pk>[^/.]+)/$' [name='book-detail']>]
# DefaultRouter
# [<URLPattern '^book/$' [name='book-list']>, <URLPattern '^book\.(?P<format>[a-z0-9]+)/?$' [name='book-list']>, <URLPattern '^book/(?P<pk>[^/.]+)/$' [name='book-detail']>, <URLPattern '^book/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='book-detail']>, <URLPattern '' [name='api-root']>, <URLPattern '<drf_format_suffix:format>' [name='api-root']>]
【3】aciton
装饰器
- 首先要强调的是必须继承ViewSetMixin的视图类才可以使用
(1)介绍
@action
装饰器是一个用于在视图集中添加自定义路由和视图方法的强大工具。- 语法:
@action(detail=False, methods=['get'], url_path='custom-list')
detail
参数:这个参数决定了该动作是否针对单个实例(True
)还是针对集合(False
)。- 如果
detail=True
,则URL将包含对象的主键,例如/myendpoint/{pk}/custom-detail/
。 - 如果
detail=False
,则URL将不包含主键,例如/myendpoint/custom-list/
。
- 如果
methods
参数:这个参数是一个列表,指定了支持哪些HTTP方法(如['get']
,['post']
,['put']
等)。url_path
参数:这个参数是自定义路由的URL部分,它将附加到视图集的URL上。默认是方法名。
(2)示例
- 要求:在一个视图类中完成登录、注册、修改密码的接口
- 代码
from rest_framework.viewsets import ViewSet
class UserAPIView(ViewSet):
@action(methods=['post'], detail=False)
def register(self, request):
return Response({'code': 100, 'msg': '注册成功'})
@action(methods=['post'], detail=False)
def login(self, request):
return Response({'code': 100, 'msg': '登录成功'})
@action(methods=['post'], detail=False)
def password(self, request):
return Response({'code': 100, 'msg': '修改成功'})