对于上次学到的视图集来说,虽然我们在编写视图逻辑代码时通过继承ModelViewSet后只需提供序列化器和模型对象查询集即可省去增删改查(查询所有数据)这五个常用的接口大量的代码。但是我们在编写路由时,又有些许的麻烦,所有drf为我们提供了routers路由集,为我们在编写视图代码继承视图集时提供自动生成路由的功能。
如下图是继承视图集ModelViewSet后编写的代码及路由。
- class _ModelViewSet(ModelViewSet):
- queryset = BookInfo.objects.all()
- serializer_class = BookSerializer
-
- #
- # --------------------ModelViewSet-----------------------------------------
- path('demo/books/', _ModelViewSet.as_view({
- 'get': 'list',
- 'post': 'create'
- })),
- re_path(r'^demo/books/(?P
\d+)/$' , _ModelViewSet.as_view({ - "get": 'retrieve',
- 'delete': 'destroy',
- 'put': 'update'
- })),
对于视图集,我们除了可以自己手动指明请求方式与动作action(视图名)之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。如果是非视图集,不需要使用路由集routers
from rest_framework.routers.DefaultRouter
如下:通过DefaultRouter自动生成路由步骤(默认自动生成list、create、delete、update、retrieve五个视图函数的路由):
- # -------------------DefaultRouter-----------------------------------------
- from rest_framework.routers import DefaultRouter
-
- # 1.实例化DefaultRouter路由对象
- routers = DefaultRouter()
-
- # 2.指定继承视图集的视图,自动生成路由
- routers.register('demo/books', _ModelViewSet, basename='demo/books/')
- for url in routers.urls:
- print(url)
- # 3.将生成的路由添加到urlpatterns中去
- urlpatterns += routers.urls
- """
- 1、对应创建模型对象和查询所有模型对象数据的路由
- 2、对应更改、查询、删除单个模型对象的路由
[a-z0-9]+)/?$' [name='demo/books/-list']> [^/.]+)/$' [name='demo/books/-detail']> [^/.]+)\.(?P[a-z0-9]+)/?$' [name='demo/books/-detail']> - 3、对应访问url路径http://127.0.0.1:8000时显示
- {
- "demo/books": "http://127.0.0.1:8000/demo/books/"
- }
- 4、对应访问url路径http://127.0.0.1:8000\时显示
- {
- "demo/books": "http://127.0.0.1:8000/demo/books/"
- }
[a-z0-9]+)/?$' [name='api-root']> - """
对应根路径的路由

对应更改、查询、删除单个模型对象路径的路由

对应创建模型对象和查询所有模型对象数据的路径路由

使用方式与DefaultRouter一致的。只是少两个根目录url路径以及将四个url路径压缩为两个。
- # -------------------SimpleRouter-----------------------------------------
- from rest_framework.routers import SimpleRouter
-
- # 1.实例化DefaultRouter路由对象
- routers = SimpleRouter()
-
- # 2.指定继承视图集的视图,自动生成路由
- routers.register('demo/books', _ModelViewSet, basename='demo/books/')
- for url in routers.urls:
- print(url)
- # 3.将生成的路由添加到urlpatterns中去
- urlpatterns += routers.urls
- 1、对应创建模型对象和查询所有模型对象数据的路由
'^demo/books/$' [name='demo/books/-list']> - 2、对应更改、查询、删除单个模型对象的路由
'^demo/books/(?P[^/.]+)/$' [name='demo/books/-detail']>
缺少的根路径路由

1、对应创建模型对象和查询所有模型对象数据的路由

2、对应更改、查询、删除单个模型对象的路由

rest_framework.decorators.action
在视图集中,如果想要让Router自动帮助我们自定义出除开(list、create、delete、update、retrieve)这五个视图函数的url路由外的路由,因为可能一个视图中不止这些方法。则我们需要在视图集中使用action装饰器。
以action装饰器装饰的视图函数方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
methods: 声明该action对应的请求方式,列表参数
detail: 声明该action的路径是否与单一资源对应
路由前缀//action方法名/
True 表示路径格式是xxx/
False 表示路径格式是xxx/action方法名/
url_path:声明该action的路由尾缀。
代码
- class _ModelViewSet(ModelViewSet):
- def get_serializer_class(self):
- if self.action == 'get_books_name':
- return BookNameSerializer
- else:
- return BookSerializer
-
- queryset = BookInfo.objects.all()
-
- @action(methods=['GET'], detail=False)
- def get_books_name(self, request):
- names = self.get_queryset()
- ser = self.get_serializer(instance=names, many=True)
- return Response(data=ser.data)
自动生成的路由
'^demo/books/get_books_name/$' [name='demo/books/-get-books-name']>
其中自动生成的后缀路由get_books_name/就是视图函数名,demo/books/为以下生成视图集路由时的前缀
routers.register('demo/books', _ModelViewSet, basename='demo/books/')
如果想后缀名/login不是由自动生成路由时的函数名,可以通过url_path自定义后缀名
- class _ModelViewSet(ModelViewSet):
- def get_serializer_class(self):
- if self.action == 'get_books_name':
- return BookNameSerializer
- else:
- return BookSerializer
-
- queryset = BookInfo.objects.all()
-
- @action(methods=['GET'], detail=False, url_path='get_name')
- def get_books_name(self, request):
- names = self.get_queryset()
- ser = self.get_serializer(instance=names, many=True)
- return Response(data=ser.data)
-
'^demo/books/get_name/$' [name='demo/books/-get-books-name']>
代码
- from rest_framework.decorators import action
- from .Serializer import BookNameSerializer
-
-
- class _ModelViewSet(ModelViewSet):
- def get_serializer_class(self):
- if self.action == 'get_books_name':
- return BookNameSerializer
- else:
- return BookSerializer
-
- queryset = BookInfo.objects.all()
- @action(methods=['GET'], detail=True, url_path='get_name')
- def get_books_name(self, request, pk):
- names = self.get_object()
- ser = self.get_serializer(instance=names)
- return Response(data=ser.data)
自动生成的路由
'^demo/books/(?P[^/.]+)/get_name/$' [name='demo/books/-get-books-name']>
