Django Rest_framework 4(APIView、GenericAPIView、ViewSet)

详解Django DRF框架中APIView、GenericAPIView、ViewSet区别
https://zhuanlan.zhihu.com/p/72527077
View->APIView->GenericAPIView->Mixin扩展类->子类视图

一、DRF类视图-APIView

APIView视图基类:
	Django框架View类的子类,在View类的基础上封装了一些功能。

功能如下:
	1. 视图request参数变成了Request类的对象,不再是Django原始HttpRequest类的对象;
		request.data: 保存解析之后的请求体中数据,已经解析为了字典或类字典(QueryDict)。								request.POST|request.body|request.FILES
		request.query_params: 保存解析之后的查询字符串。request.GET
		
	2. 响应时可以统一返回Response类的对象,DRF框架会根据客户端请求头的`Accept`将响应数据转换为对应数据格式进行返回,默认返回json,仅支持html或json;
		`Accept: text/html`:将响应数据转换为html进行返回
		`Accept: applicaiton/json`:将响应数据转换为json进行返回
		return Response(响应数据)
	
	3. 异常处理:如果视图出现了未处理的异常,DRF框架会对异常进行处理,并将处理的错误响应返回给客户端;
	4. 认证&权限&限流

二、类视图-GenericAPIView

GenericAPIView视图基类:
	继承自APIView,在APIView类的基础上封装了一些功能。
	
	class 类视图(GenericAPIView):
			serializer_class = <序列化器类> #指明视图所使用的序列化器类;
			queryset = <查询集> 			#指明视图所使用的查询集
	
功能如下:
	1. 封装了操作序列化器的属性和方法:
		方法:
			get_serializer_class:获取视图所使用的序列化器类;
					
				eg:如果根据不同的action动作使用不同的额序列化器,需要重写此方法;
				#视图集对象.action:获取所有执行的操作
				
				def get_serializer_class(self):
					if self.action=="retrieve":
						return BookDetailSerializer
					return BookSerializer
					
			get_serializer:创建一个视图所使用的序列化器类的对象;	
			从类属性serializer_class中获得serializer的序列化类,提供给Mixin扩展类使用。
	
	2. 封装了查询数据库的属性和方法:	
		方法:
			get_queryset:获取视图所使用的查询集,
						  群操作就走get_queryset()方法(包括群查,群增等)
			get_object:从视图所使用的查询集中查询指定的对象(默认根据pk主键进行查询),
            			 单操作就走get_object()方法(包括单查,单增等)
          
         eg:重写get_queryset
         	#获取当前用户的登录地址
         	def get_queryset(self):
         		return UserAddress.objects.filter(user = self.request.user)
         		
         eg:重写get_object:
         	#1.获取URL传递过来的参数:id=self.kwargs['pk']
         	定义类视图之后,类视图对象有一个属性kwargs字典,保存从url地址中提取的所有命名参数;
         	
         	#2.取到当前的用户对象:user = self.request.user
         	请求后台时前端header中携带token认证,在后台就可以用request 取到当前的用户对象;
         def get_object(self):
            user = self.request.user
            goodsid=self.kwargs['pk']
            userfav = UserFav.objects.filter(user=user, goods_id=goodsid).first()
                return userfav
                
                
                
          重写perform_create
            #将购物车中所有物品结算(删除购物车并将物品移至订单表中)
                def perform_create(self, serializer):
                order = serializer.save()  # 创建一笔订单
                global order_sn
                order_sn += 1
                order.order_sn = '000000' + str(order_sn)
                order.save()
                shopcarts = ShoppingCart.objects.filter(user=self.request.user)
                for shopcart in shopcarts:
                    orderGoods = OrderGoods()
                    orderGoods.goods_num = shopcart.nums
                    orderGoods.goods = shopcart.goods
                    orderGoods.order = order
                    orderGoods.save()

                    # delete
                    shopcart.delete()
			
	3. 过滤&分页
            pagination_class 分页控制类 
            filter_backends  过滤控制后端 

三、类视图-Mixin扩展类的功能&使用

继承自GenericAPIView之后,使用GenericAPIView中提供的操作序列化器的函数和数据库查询的函数写出的代码变成了通用代码,这些通用代码抽取之后,就是DRF框架提供的5个Mixin扩展类。

Mixin扩展类:
	ListModelMixin(群查):list,封装了获取一组数据通用流程。
							#除了查询,该list方法会对数据进行过滤和分页
	CreateModelMixin(单增):create,封装了新增一条数据通用流程。
							#注意:没有群增的方法,需要自己手动写(******)
	RetrieveModelMixin(单查):retrieve,封装了获取指定数据通用流程。
	UpdateModelMixin(更新,修改):update,封装了更新指定数据通用流程。
								#只有单整体改和单局部改,没有群整体改和群局部改
	DestroyModelMixin(删除):destroy,封装了删除指定数据通用流程。
视图作用可使用方法父类
ListAPIView查询多条数据getGenericAPIView ListModelMixin
CreateAPIView新增一条数据postGenericAPIView CreateModelMixin
RetrieveAPIView查询一条数据getGenericAPIView RetrieveModelMixin
UpdateAPIView修改一条数据put,patchGenericAPIView UpdateModelMixin
DestroyAPIView删除一条数据deleteGenericAPIView DestroyModelMixin
RetrieveUpdateAPIView单查,更新一条数据get,put,patchGenericAPIView RetrieveModelMixin UpdateModelMixin
RetrieveUpdateDestroyAPIView单查,更新,删除一条数据get,put,patch,deleteGenericAPIView RetrieveModelMixin UpdateModelMixin DestroyModelMixin
ListCreateAPIView群查,更新一条get,post

四、视图集-ViewSet视图集的功能&使用

视图集:将操作同一组资源的处理函数放在同一个类中,这个类就是视图集。

视图集和类视图的区别?
答:实现同一组接口时,如果使用类视图可能需要多个类视图,而使用视图集时只需要一个视图集。
	比如:实现图书管理的5个接口时,使用类视图用了2个类视图:BookListVIew和BookDetailView,如果使用视图集只需要一个即可。
	
基本使用:
	1. 继承自ViewSet(继承自ViewSetMixin和APIView)
	2. 视图集中的处理函数不再以请求方式(比如:get,post等)命名,而是以对应的action操作命名,常见操作如下:
		ListModelMixin:获取一组数据
		createModelMixin:创建一条数据
		retrieveModelMixin:获取指定数据
		updateModelMixin:修改指定数据
		destroyModelMixin:删除指定数据
	3. 在urls.py进行url地址配置时需要明确指明某种请求方式请求某个地址对应的是视图集中的哪个处理函数。

五、视图集-视图集父类GenericViewSet使用

继承自ViewSetMixin和GenericAPIView,可以配合Mixin扩展类提供对应的处理函数
 1)工具视图都是GenericAPIView的子类,且不同的子类继承了不同的工具类
 2)工具视图的功能可以满足需求,只需要继承工具视图,并且提供queryset与serializer_class即可
 
 GenericViewSet通常配合Mixin扩展类进行使用。

class TestViewSet(ListModelMixin, GenericViewSet):
	serializer_class=""
	queryset=""
六、视图集-视图集父类ModelViewSet和ReadOnlyModelViewSet使用
ModelViewSet:继承了5个Mixin扩展类,同时继承了GenericViewSet
ReadOnlyModelViewSet:继承了ListModelMixin, RetireveModelMixin,同时继承了GenericViewSet

需求:
	写一个视图集,提供一下2个API接口:
	1. 获取所有的图书 GET /books/ -> list
	2. 获取指定的图书 GET /books/(?P<pk>\d+)/ -> retrieve
	
	class BookInfoViewSet(ReadOnlyModelViewSet):
		queryset = BookInfo.objects.all()
		serializer_class = BookInfoSerializer

七、视图集比较

1.常用视图集父类
  ViewSet
  继承自APIView和ViewSetMixin,没有提供任何方法,需要自己写
  GenericViewSet
  继承GenericAPIView和ViewSetMixin,其中GenericAPIView提供了基础方法,可以直接搭配Mixin扩展类使用,所以我们选这个
  ModelViewSet  
  继承GenericViewset,但同时也包括ListModelMixin、CreateModelMixin等mixin扩展类

1)视图集都是默认优先继承ViewSetMixin类,再继承一个视图类(GenericAPIView或APIView) 
2)ViewSetMixin提供了重写的as_view()方法,继承视图集的视图类,配置路由时调用as_view()必须传入 请求名-函数名 映射关系字典
       eg: url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
       表示get请求会交给my_get_list视图函数处理

八、路由Router

作用:动态生成视图集中处理函数的url配置项。

使用:
1. 创建Router类的对象
	#DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。
	router = SimpleRouter()
	router = DefaultRouter()
2. 注册视图集
	router.register(<prefix>, <viewset>, <base_name>)
	例如:router.register('books', views.BookInfoViewSet, base_name='books')
3. 将动态生成的配置项列表添加到urlpatterns中
	方法一:urlpatterns += router.urls
	方法二:urlpatterns = [
                            path(r'^', include(router.urls)),
                        ]
	方法三:urlpatterns.extend(router.urls)

九、常见问题

1.GenericAPIView与APIView两大继承视图的区别
1)GenericViewSet和ViewSet都继承了ViewSetMixin,as_view都可以配置 请求-函数 映射
2)GenericViewSet继承的是GenericAPIView视图类,用来完成标准的 model 类操作接口
3)ViewSet继承的是APIView视图类,用来完成不需要 model 类参与,或是非标准的 model 类操作接口
      post请求在标准的 model 类操作下就是新增接口,登陆的post不满足
      post请求验证码的接口,不需要 model 类的参与
案例:登陆的post请求,并不是完成数据的新增,只是用post提交数据,得到的结果也不是登陆的用户信息,而是登陆的认证信息
2.类视图和视图集区别?
 答:实现同一组接口时,如果使用类视图可能需要多个类视图,而使用视图集时只需要一个视图集。
 	比如:实现图书管理的5个接口时,使用类视图用了2个类视图:BookListVIew和BookDetailView,如果使用视图集只需要一个即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值