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根视图,返回一个包含所有列表视图的超链接响应数据。

posted @ 2023-02-03 20:58  断浪狂刀忆年少  阅读(47)  评论(0编辑  收藏  举报