DRF(Django rest_framework)(2 视图部分和路由)

这边先分享一个DRF的比较全的各种组件的用法的地址(DRF | YUAN),但是讲得比较专业,我这边更通俗,是按照封装过程来讲解的,所以可能会更清晰一步一步怎么来的,为什么

DRF视图!!!!!

DRF视图

DRF提供的视图的主要作用:

基于View的接口(原生)

from   django.views   import   View

就是从FBV到CBV的第一步,面向资源编程,将对一个资源的操作全放到一个类中,需要继承View类,是所有基于类的view的父类,它负责将视图连接到URL、HTTP 方法调度,需要在url模式中改成cccView.as_view()  ,as_view()返回view函数,如图:

DRF(Django rest_framework)(2 视图部分和路由)_第1张图片DRF(Django rest_framework)(2 视图部分和路由)_第2张图片

基于APIView的接口(第一步封装request)

from   rest_framework.view    import   APIView

它是继承自Django的View的,

重写了as_view()方法和dispatch()方法的分发逻辑,还小干了一些事情,执行了父类的as_view()方法,最后也是返回view函数

最不一样的就是dispatch():构建了新的request对象,初始化:认证、限流、限流组件

Django,View中的request是request.POST和request.GET,且不会解析JSON数据,因为其针对的是urlencoded的数据

APIView中新构建的request对象,是request.data和request.query_param,所以拿请求体的数据时会异常方便!(request._request会取到Django原生的request)如图:

DRF(Django rest_framework)(2 视图部分和路由)_第3张图片

基于GenericAPIView的接口实现(第二步封装接口中序列化器的操作)

 from  rest_framework.generics import GenericAPIView

GenericAPIView是继承自APIView,主要曾加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个多个Mixin扩展类

为什么要GenericAPIView??因为我们发现在不断重复增删改查查的逻辑中,查询出来的数据和序列化器都是一直不变的,那么就可以直接抽象出来(是关键字,一个字都不能错),以后想对哪个表做基本的五个接口,只需要改动queryset和serializer_class即可

提供的关于序列化器使用的属性与方法,这四个方法主要是调度用的(在GenericAPIView的源码中被定义)

1.  get_serializer_class(self) 

获取序列化器类(前提是已经在view视图下放好了全局变量serializer_class)

调用方法:self.get_serializer_class()

2.  get_serializer(self,args, *kwargs) 

获取序列化器对象  (前提是已经在view视图下放好了全局变量serializer_class),这个内部会调用获取序列化器类,并实例化后返回对象

3. get_queryset(self)

获取查询集结果(前提是已经在view视图下放好了全局变量queryset)

调用方法:   self.get_queryset()

4.get_object(self)

获取单一资源对象(主要是使用在查取单个对象的接口中),它内部会找出queryset,并且不又名参接受位置参数的传参,而是只接受有名分组的传参,必须叫pk,它才会按照关键字传参

现在基于上面的这部分知识来完成这View接口

1.查所有get接口(View中)

DRF(Django rest_framework)(2 视图部分和路由)_第4张图片

2.增加post接口(View中)

同理

DRF(Django rest_framework)(2 视图部分和路由)_第5张图片

3.查单个get接口(DetailView中)

注意参数是ok和get_object()会直接拿到模型类对象

DRF(Django rest_framework)(2 视图部分和路由)_第6张图片

4.更新单个put接口(DetailView中)

同理:

DRF(Django rest_framework)(2 视图部分和路由)_第7张图片

5.删除单个delete接口(DetailView中)

DRF(Django rest_framework)(2 视图部分和路由)_第8张图片

基于MixIN混合类的接口实现(第三部封装五个接口方法内部的所有操作)

from rest_framework.mixins import ListModeMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin

用GenericAPIView时,五个接口内部的逻辑完全可以封装起来,然后直接调用,而不是一个表就再粘贴一遍,DRF给封装好了

1.ListModeMixin

ListModeMixin中有list方法,就是增加了一个过滤和分页,然后就取所有,并做序列化返回serializer.data,和之前的逻辑一模一样,如图:

DRF(Django rest_framework)(2 视图部分和路由)_第9张图片

所以写接口的时候就可以通过GenericAPIView和ListModelMixin配合着直接来:

DRF(Django rest_framework)(2 视图部分和路由)_第10张图片

2.CreateModelMixin

CreateModelMixin中封装了create方法,就是post,还有perform_create方法,只有.save()

DRF(Django rest_framework)(2 视图部分和路由)_第11张图片

所以也直接来:

DRF(Django rest_framework)(2 视图部分和路由)_第12张图片3.RetrieveModelMixin

RetrieveModelMixin中是retrieve方法

DRF(Django rest_framework)(2 视图部分和路由)_第13张图片

4.UpdateModelMixin

UpdateModelMixin中是update方法,直接来

DRF(Django rest_framework)(2 视图部分和路由)_第14张图片5.DestroyModelMixin

DestroyModelMixin中是destroy方法,并返回一个空的对象,如图:

DRF(Django rest_framework)(2 视图部分和路由)_第15张图片

直接来看到最终的DetailView:

DRF(Django rest_framework)(2 视图部分和路由)_第16张图片

基于Minni混合类的再封装(第四步封装多个接口成一个类继承)

实现了上面的接口后,发先虽然五个接口内部都只剩一句话了,但是还是需要对每一个表写五次,所以进行再封装,

View的封装在一块(get,post,ListModeMixin,CreateModelMixin,GenericAPIView是一个整体),变成ListCreateAPIView

DetailView的封装在一块(get,put,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,GenericAPIView是一个整体)

1. from rest_framework.generics import ListCreateAPIView

如图ListCreateAPIView的源码:

DRF(Django rest_framework)(2 视图部分和路由)_第17张图片

所以只需要这样实现接口,不需要写这些方法了      :

DRF(Django rest_framework)(2 视图部分和路由)_第18张图片

2.from rest_framework.generics import RetrieveUpdateDestroyAPIView

同理DetailView中的接口只需这样实现:

基于View工具类进行接口开发(第五次封装改变了分发机制并且只剩一个视图函数)

基于对上面的理解,之所以一个资源需要用两个View类,是因为分发逻辑时根据请求方式,所以两个类中用的是一套变量,即序列化器和query_set;所以想要将五个方法写在一个类中,必然需要改变分发机制

看一下ViewSet的源码,发现它没有继承GenericView,所以Mixins混合类都不能用

DRF(Django rest_framework)(2 视图部分和路由)_第19张图片

因为ViewSet这个类继承了ViewSetMixin,那么路由的as_view()中就可以加参数了,参数是一个字典,制定了请求方式到视图类中方法的映射,例如请求方式为get且含数字的对于的方法名是get_object; 如图所示:

那么ViewSetMixin干了什么来改变分发逻辑的呢??,最重要的就是下面的图中展示的,将字典(每个action就是一个字典)按照键值对取出,并将value用getattr()将value反射成函数变量,然后再给method设置成这个函数变量,所以当取到get字符串的时候就直接拿到自己写的这个函数变量了(相当于我拦截你一下,让你别找get了,找我让你找到):

from rest_framework.viewsets import ViewSet

有了映射就可以跟着映射给函数取名了

DRF(Django rest_framework)(2 视图部分和路由)_第20张图片

基于GenericViewSet的最终版本

先看GenericViewSet的源码

DRF(Django rest_framework)(2 视图部分和路由)_第21张图片

发现是继承了ViewSetMixin(完成了路由的重新分发),和GenericAPIView(调度的各种方法);是这两种的组合,所以此时有了generic的调度方法就可以使用ListModeMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin了,这五个类中的五个方法:list、create、update、retrieve、destroy;;那是不是就能充当路由的字典当中的value值了;

本质逻辑就是将:ViewSetMixin的函数对应功能和GenericAPIView给结合起来了,使得可以用这五个混合类

所以最后就可以这样写:

最后最后的小小封装(这个不一定好):

ModelViewSet什么都没干,就将上面的几个类都继承了

DRF(Django rest_framework)(2 视图部分和路由)_第22张图片

DRF(Django rest_framework)(2 视图部分和路由)_第23张图片

最后的这个确实好用但是,会失去灵活性,不能自定义逻辑,所以有时候需要将比如ListModeMixin拿过来之后,自己在View类中重写list函数来覆盖掉ListModeMixin中的list

注册路由!!!!

注册路由

原来的路由看上去就很复杂,很不好用不好写,所以去使用注册路由就很方便

1.生成个默认的路由对象

DRF(Django rest_framework)(2 视图部分和路由)_第24张图片

第一个参数就是url最后的那个资源,不用斜杠;每注册一个都会生成一个之前写的path和一个re_path

在列表外面再加上:即可

你可能感兴趣的:(django,python,后端,restful)