drf之路由Routers
# 2. 路由Routers
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。如果是非视图集,不需要使用路由集routers
REST framework提供了两个router类,使用方式一致的。结果多一个或少一个根目录url地址的问题而已。
- **SimpleRouter**
- **DefaultRouter**
## 2.1 使用方法
1) 创建router对象,并注册视图集,例如
from django.urls import path from . import views urlpatterns = [ # 省略.... # path("s7/", views.StudentMixinViewSet.as_view({"get":"list","post":"create"})), # path("s7/<int:pk>/", views.StudentMixinViewSet.as_view({"get":"retrieve","put":"update","delete":"destroy"})), ] # 路由集的操作 from rest_framework.routers import DefaultRouter,SimpleRouter router = DefaultRouter() # 注册视图(访问前缀,视图集类,调用别名) router.register("s7", views.StudentMixinViewSet, "s7") # 把路由对象生成的视图集路由列表合并追加路由列表中 print(router.urls) urlpatterns += router.urls
register(prefix, viewset, basename)
- prefix 该视图集的路由前缀
- viewset 视图集
- basename 路由别名的前缀
如上述代码会形成的路由如下:
url: ^s7/$ basename: s7-list
url: ^s7/(?P<pk>[^/.]+)/$ basename: s7-detail
2)把路由对象生成的视图集的路由列表添加到django的路由中可以有两种方式:
```python urlpatterns = [ ... ] urlpatterns += router.urls ``` 或 ```python from django.urls import include,re_path urlpatterns = [ ... re_path('^', include(router.urls)) ] ```
## 2.2 视图集中附加action的声明
在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用`rest_framework.decorators.action`装饰器。 以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。 action装饰器可以接收两个参数: - **methods**: 声明该action对应的请求方式,列表参数 - **detail**: 声明该action的路径是否与单一资源对应 ``` 路由前缀/<pk>/action方法名/ ``` - True 表示路径格式是`xxx/<pk>/action方法名/` - False 表示路径格式是`xxx/action方法名/` - url_path:声明该action的路由尾缀。
举例:
from rest_framework.viewsets import ModelViewSet from rest_framework.decorators import action class StudentModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer # 路由对象给视图集生成路由信息时,只会生成5个基本api接口,这主要是router只识别5个混入类的原因, # 而针对我们开发者自定义的视图方法,路由对象不会自动生成路由信息, # 所以下面这个login,如果希望被外界访问到,则必须通过action装饰器告诉路由对象要给它生成一个路由信息。 @action(methods=["get","post"], detail=False, url_path="login") # action的参数 # methods, 列表,指定允许哪些http请求方法可以访问当前视图方法 # detail, 布尔值,告诉路由对象在生成路由信息时,是否要自动生成pk值,True表示需要,False表示不需要。 # url_path,字符串,访问视图的url地址,如果不设置,则默认采用视图方法名作为访问后缀 # http://127.0.0.1:8000/demo/student9/login/ def login(self, request): """登录视图""" return Response({"msg":"登录成功"}) @action(methods=["get"], detail=True, url_path="login/log") # http://127.0.0.1:8000/demo/student9/20/login/log/ def login_log(self,request,pk): """用户登录历史记录""" # 视图集类中比普通的视图类,多一个属性,action # 可以通过self.method获取本次客户端的http请求 # 可以通过self.action获取本次客户端请求的视图方法名[ViewSet提供的] print(self.action) # login_log return Response({"msg": "用户登录历史记录"})
由路由器自动为此视图集自定义action方法形成的路由会是如下内容:
url: ^student9/login/$ basename: student9-login
url: ^student9/(?P<pk>[^/.]+)/login/log/$ basename: student9-login-log
## 2.3 路由router形成URL的方式
1) SimpleRouter(prefix=“路由前缀”,viewset=视图集类,basename=“路由别名”)
2)DefaultRouter
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
幻想毫无价值,计划渺如尘埃,目标不可能达到。这一切的一切毫无意义——除非我们付诸行动。