本文共 6792 字,大约阅读时间需要 22 分钟。
上一篇我们说了使用GenericAPIView的视图子类进一步简化,这一篇基于ViewSet进行进一步简化。
继承自APIView
与ViewSetMixin
,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:‘list’})的映射处理工作。
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
1.在Views视图中写如下代码:
from rest_framework.viewsets import ViewSet,GenericViewSetclass Students5View(ViewSet): # 获取所有数据接口 def get_all_student(self,request): # action all_data = models.Student.objects.all() serializer = StudentSerializer(instance=all_data,many=True) return Response(serializer.data) # 添加一条记录的接口 def add_student(self,request): data = request.data serializer = StudentSerializer(data=data) if serializer.is_valid(): instance = serializer.save() #instance为添加的新纪录对象 serializer = StudentSerializer(instance=instance) return Response(serializer.data,status=status.HTTP_201_CREATED) else: print(serializer.errors) def get_one(self,request,pk): stu_obj = models.Student.objects.get(pk=pk) serializer = StudentSerializer(instance=stu_obj) return Response(serializer.data)
2.路由:
urlpatterns = [ path('students5/', views.Students5View.as_view({ 'get':'get_all_student','post':'add_student'})), re_path('students5/(?P\d+)/', views.Students5View.as_view({ 'get':'get_one'}))]
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖于GenericAPIView
,所以还需要继承GenericAPIView
。
GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView
与ViewSetMixin
,在实现了调用as_view()时传入字典(如{'get':'list'}
)的映射处理工作的同时,还提供了GenericAPIView
提供的基础方法,可以直接搭配Mixin扩展类使用。
1.在Views中写入:
from rest_framework.viewsets import ViewSet,GenericViewSetclass Students6View(GenericViewSet): queryset = models.Student.objects.all() serializer_class = StudentSerializer # 获取所有数据接口 def get_all_student(self,request): # action all_data = self.get_queryset() serializer = self.get_serializer(instance=all_data,many=True) return Response(serializer.data) # 添加一条记录的接口 def add_student(self,request): data = request.data serializer = StudentSerializer(data=data) if serializer.is_valid(): instance = serializer.save() #instance为添加的新纪录对象 serializer = StudentSerializer(instance=instance) return Response(serializer.data,status=status.HTTP_201_CREATED) else: print(serializer.errors) def get_one(self,request,pk): stu_obj = models.Student.objects.get(pk=pk) serializer = StudentSerializer(instance=stu_obj) return Response(serializer.data)
2.路由
urlpatterns = [ path('students6/', views.Students6View.as_view({ 'get':'get_all_student','post':'add_student'})), re_path('students6/(?P\d+)/', views.Students6View.as_view({ 'get':'get_one'}))]
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
1.在Views中写入·:
from rest_framework.viewsets import ViewSet,GenericViewSetfrom rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixinclass Students7View(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin): queryset = models.Student.objects.all() serializer_class = StudentSerializer # 获取所有数据接口 def get_all_student(self,request): # action return self.list(request) # 添加一条记录的接口 def add_student(self,request): return self.create(request) def get_one(self,request,pk): return self.retrieve(request,pk) def update_one(self,request,pk): return self.update(request,pk) def delete_one(self,request,pk): return self.destroy(request,pk)
2.路由
urlpatterns = [ path('students7/', views.Students7View.as_view({ 'get':'get_all_student','post':'add_student'})), re_path('students7/(?P\d+)/', views.Students7View.as_view({ 'get':'get_one'}))]
使用ModelViewSet简写上面的继承代码
1.在Views中写入:
from rest_framework.decorators import actionfrom rest_framework.viewsets import ModelViewSetclass Students8View(ModelViewSet): queryset = models.Student.objects.all() serializer_class = StudentSerializer def login(self,request,pk): return Response({ 'msg':'success'})
2.路由:
urlpatterns = [ path('students8/', views.Students8View.as_view({ 'get':'list','post':'create'})), re_path('students8/(?P\d+)/', views.Students8View.as_view({ 'get':'retrieve','put':'update','delete':'destroy'})), re_path('students8/login/', views.Students8View.as_view({ 'get':'login',})),
所以Views中的应该这样写:
from rest_framework.decorators import actionfrom rest_framework.viewsets import ModelViewSetclass Students8View(ModelViewSet): queryset = models.Student.objects.all() serializer_class = StudentSerializer # 想让defultrouter帮你 @action(methods=['get'], detail=True) #detail=True自动生成带参数的路径,False生成不带参数的路径 def login(self,request,pk): return Response({ 'msg':'success'})
REST framework提供了两个router
(1) 创建router对象,并注册视图集,例如
from rest_framework import routersrouter = routers.DefaultRouter()router.register('dd',views.Students8View)
(2)添加路由数据
可以有两种方式:
方式1 简单一些
urlpatterns = [ ...]urlpatterns += router.urls
或
方式2
urlpatterns = [ ... url(r'^', include(router.urls))]
使用路由类给视图集生成了路由地址
from rest_framework.decorators import actionfrom rest_framework.viewsets import ModelViewSetclass Students8View(ModelViewSet): queryset = models.Student.objects.all() serializer_class = StudentSerializer # 想让defultrouter帮你 @action(methods=['get'], detail=True) #detail=True自动生成带参数的路径,False生成不带参数的路径 def login(self,request,pk): return Response({ 'msg':'success'})
路由代码:
from django.urls import path, re_pathfrom . import viewsurlpatterns = [ path('dd/', views.Students8View.as_view({ 'get':'list','post':'create'})), re_path('dd/(?P\d+)/', views.Students8View.as_view({ 'get':'retrieve','put':'update','delete':'destroy'})), re_path('dd/login/', views.Students8View.as_view({ 'get':'login',}))]"""使用drf提供路由类router给视图集生成路由列表"""# 实例化路由类# drf提供一共提供了两个路由类给我们使用,他们用法一致,功能几乎一样from rest_framework.routers import DefaultRouterrouter = DefaultRouter()# 注册视图集router.register("router_stu",views.StudentModelViewSet)# 把生成的路由列表追加到urlpatternsprint( router.urls )urlpatterns += router.urls
转载地址:http://cgqzi.baihongyu.com/