DRF即
Django REST Framework
的缩写,官网上说:Django REST framework
是一个强大而灵活的工具包,用于构建Web API。
简单来说:通过DRF创建API后,就可以通过HTTP请求来获取、创建、更新或者删除数据(CRUD)
DRF(django rest framework)是基于django的一个框架,可以帮助我们快速开发restful规范的的接口框架https://www.django-rest-framework.org/
在开发Web应用中,有两种应用模式:
前后端混合项目是指前后端代码的混合,前端需要使用模版语法去获取后端的数据,后端需要使用locals在开放局部空间来让前端拿到数据。
大体流程就是:前端在编写完静态页面之后,需要发送给后端人员做二次处理,所有的html代码和数据在服务器拼接好,等前后端处理好模版之后在做整合,然后一次性将所有内容发送到客户端,浏览器执行代码,将内容呈现给客户。
前后端分离开发模式是指代码上的分离,
前后端代码上面的数据传输和交互使用API接口的方式使用Json格式的数据进行交互,脱离了模版语法
。也就是说前后端与浏览器的交互是分开的把界面交互和数据交互分开(这里的数据交互必须是Json格式或者XML,现在XML基本很少了)
,后端人员向前端开放数据接口(路由),视图层不在直接返回给浏览器了,而是与前端做起了数据交互,实际上返回界面的还是前端,前端工作人员调用接口获取数据,从而将数据显示到页面
大体流程:浏览器发送请求,这时候前端返回一个静态页面,当静态页面中触发js事件的时候,通过Ajax向服务器端发送请求,索要数据,然后将数据拿到之后再填充到浏览器的页面中。
而当需要数据测试的时候,前端可以使用
Mock
平台来模拟接口数据,而后端可以使用软件Apifox
或者Postman
模拟前端发送请求。
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。API除了有应用“应用程序接口”的意思外,还特指 API的说明文档,也称为帮助文档。
API:应用程序接口(API:Application Program Interface)是一组定义、程序及协议的集合,通过 API 接口实现计算机软件之间的相互通信。API 的一个主要功能是提供通用功能集。程序员通过调用 API 函数对应用程序进行开发,可以减轻编程任务。 API 同时也是一种中间件,为各种不同平台提供数据共享。
简单理解API:
为了在团队内部形成共识、防止因个人习惯差异引起的混乱,我们需要找到并形成团队共识、统一的接口规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。
通过网络,规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介
http://127.0.0.1:8000/login/ 这就是API接口
Web API接口和一般的url链接还是有区别的,Web API接口简单概括有四大特点:
1.url地址:长得像返回数据的url链接
https://api.map.baidu.com/place/v2/search
2.请求方式:get、post、put、patch、delete
采用get方式请求上方接口
3.请求参数:Json格式或者XML格式的key-value类型数据
'请求数据:地址栏中的数据----->request.GET,请求体中数据:reqeust.POST'
早些年 前后端交互使用XML格式,ajax其实就是异步JavaScript和XML
后来 随着Json格式的出现,乃至今日都是主流
未来 可能会有更高效、安全的交互格式会替代目前的Json格式
4.响应结果:Json格式或者XML格式的数据
JSON
是JavaScript Object Notation
;XML
是可扩展标记语言JSON
是基于JavaScript
语言;XML
源自于SGML
JSON
是一种表示对象的方式;XML
是一种标记语言,使用标记结构来表示数据项。JSON
不提供对命名空间的任何支持;XML
支持名称空间JSON
支持数组;XML
不支持数组XML
的文件相对难以阅读和解释;而JSON
相比较XML
的文件非常易于阅读JSON
支持结束标记;XML
有开始和结束标签JSON
的安全性较低;XML
比JSON
更安全JSON
不支持注释;XML
支持注释SON
仅支持UTF-8编码
;XML
支持各种编码前后端是指代码上的,前后台是指用户视觉上的。
前端指的是大前端,不仅仅是网站,还有app、小程序。而后端指的是Python、Golang、Java等的Web后端
Postman/Apifox
Postman是一款接口调试工具,是一款免费的可视化软件,同时支持各种操作系统平台。主要功能是发送http请求。
Postman可以直接去官网地址下载:https://www.postman.com/downloads/,然后傻瓜式安装即可
Apifox也是一款接口调试工具,也是免费的可视化软件,相较而言我觉得是比Postman更好用一下。
Apifox = Postman + Swagger(接口文档) + Mock(假数据) + JMeter(压测工具)
Apifox也是直接去官网地址下载:https://apifox.com/,下载后安装选择自己想要安装的位置即可
因为这两款软件操作都差不多,我这里就使用一下Apifox软件来展示吧
也可以看一下Postman的吧,Postman也是需要注册才可以使用,而Apifox只需要微信扫码即可
但是Postman无需创建团队以及创建项目即可使用,如下
当然市面上还有很多接口测试软件,有些是软件的也有些是网页的,具体看个人喜好选择。
Postman、Eolink、SoapUI、JMeter、REST-Assured、apizza、Postwoman
等等这些。
REST全称是
Representational State Transfer
中文意思是表述(表征行状态转移)
,它首次出现在2000年Roy fielding的博士论文中。是一种Web服务API接口的设计风格,主要适用于前后端分离的应用模式中。
这种风格的理念认为后端开发任务就是提供数据的,对外提供的事数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源,事实上我们可以使用任何一个框架都可以实现符合restful规范的api接口
https(http+ssl/tsl)
协议
API地址中带接口标识
,一般放在地址栏中(放在域名中) https://api.baidu.com (这种就是放在域名中)
https://baidu.com/api
'''看到API关键字,就代表该请求URL链接是完成齐纳后端数据交互的'''
https://api.weibo.com/2/
https://api.weibo.com/v2/
https://api.weibo.com/?version=2
https://api.weibo.com/v1/login ---->如需要的参数为name和password
https://api.weibo.com/v2/login ---->如需要的参数为name和password和code
'''
URL链接中的版本就是不同数据版本的体现,如一个app新老版本不同的接口,不能合并直接在一个接口上迭代,需要重构一个接口用于
新版本使用的,而旧接口则给老版本使用。毕竟用户可能不太想更新,如果直接迭代升级可能添加了东西需要多余的参数才能使用
'''
https://api.baidu.com/v1/users
https://api.baidu.com/books
'错误示范'
https://api.baidu.com/v1/get_users
'特殊的接口可以出现动词,因为这些接口没有一个明确的资源,或是动词就是接口的核心含义'
https://api.baidu.com/login
https://api.baidu.com/books get请求:获取所有图书
https://api.baidu.com/books/1 get请求:获取主键为1的图书
https://api.baidu.com/books post请求:新增一本图书
https://api.baidu.com/books/1 put请求:整体修改主键为1的图书
https://api.baidu.com/books/1 patch请求:局部修改主键为1的图书
https://api.baidu.com/books/1 delete请求:删除主键为1的图书
'通过在url上传参的形式传递搜索条件'
https://api.baidu.com/v1/zoos?name=猴子
响应状态码(两套)
响应状态码1xx 请求正在处理
响应状态码2xx 200:常规请求 201:创建成功
响应状态码3xx 301:永久重定向 302:暂时重定向
响应状态码4xx 403:请求无权限 404:请求路径不存在
响应状态码5xx 500:服务器异常
如:
错误代码 错误信息 详细描述
10001 System error 系统错误
10002 Service unavailable 服务暂停
10003 Remote service error 远程服务错误
返回数据中带错误信息
{'code':100,'Message':'send success'}
GET 获取所有数据 /collection 返回资源对象的列表(数组)[{'name':'西游记','price':66},{'name':'东游记','price':77}]
GET 单个对象 /collection/resource 返回单个资源对象 {'name':'西游记','price':66}
POST 新增对象 /collection 返回新生成的资源对象 {'name':'新西游记','price':77}
PUT 修改对象 /collection/resource 返回完整的资源对象 {'name':'新西游记','price':77}
PATCH 修改对象 /collection/resource 返回完整的资源对象 {'name':'新西游记','price':77}
DELETE 删除 /collection/resource 返回一个空文档
"url": "http://blog.sina.com.cn/zaku",
api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把[数据转换格式],序列化可以分为两个阶段
把我们能识别的数据结构(python的字典,列表,对象)转换成其他语言(程序)能识别的数据结构
python的字典,列表,对象--------》转换成json格式字符串(可以是别的格式)
前后端交互,目前通常使用,json格式字符串交互
前后端分离模式中,主要指:
'''
前端发送请求获取数据,后端去数据库中查询,因为查出来的是模型对象(QuerySet对象),
但是模型对象数据无法直接提供给前端或者别的平台使用,所以需要把数据进行序列化后变成字符串或者json数据,
然后返回给前端的这个过程,称之为序列化
'''
把其它程序(语言)提供的数据转换成(还原成)我们能够识别的数据结构
前端给我们的json格式数据-------》转换成字典,列表,对象
前后端分离模式中,主要指的是:
'''
前端携带json格式数据到后端,对应python而言就是字符串,需要进行反序列化成模型类对象,
然后通过ORM操作保存到数据库中的这个过程,称之为反序列化
'''
'以后写的接口,基本都是5个接口及其变形'
查询所有:JsonResponse HttpResponse
查询单个:根据pk查到单个对象,直接序列化后返回给前端
新增一个:request.POST 取出前端传入body的数据,只能取出form-data,urlencoded,不能取出josn格式,request.body --->json--->反序列化成字典,再用(name=lqz&age=19)
修改一个:put请求放到body中的数据,在request.POST取不出来,只能自己从request.body中取出来
删除一个:通过pk直接删除
'基于books单表为例,写5个接口'
创建book表
表迁移
录入表的数据:直接录入/后台管理录入
写查询所有接口 遵循restful规范,使用cbv
新增一个数据 post()
查询一个数据 get()
修改一个数据:put提交的数据,不能从requets.POST中提取,>>>request.body
删除一个数据 delete()
1.模型层urls.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
'''这里我就没去settings中修改默认数据库了,直接使用自带的sqlite3演示'''
记得创建好需要执行迁移命令:
python38 manage.py makemigrations
python38 manage.py migrate
2.视图层views.py
'''
注意:写查询所有接口 遵循restful规范,然后使用cbv的方式写
注意用到提交数据,修改数据的情况,需要注释crsf第四个中间件,否则过不了csrf认证
'''
from django.views import View
from app01 import models
from django.http import JsonResponse
import json
class BookView(View):
def get(self, request):
book_list = models.Book.objects.all()
l = []
for book in book_list:
l.append({'name': book.name, 'price': book.price})
return JsonResponse({'code': 100, 'msg': '查询成功', 'results': l})
def post(self,request):
'''
新增(可以使用urlencoded或form-data编码,使用json形式编码也行,
使用urlencode或form-data编码,就得从request.POST中去取,一个个取
使用json形式编码,json格式编码提交的数据,需要反序列化后,从request.body中取)
'''
data = json.loads(request.body)
print(data)
book = models.Book.objects.create(**data)
return JsonResponse({'code': 100, 'msg': '添加成功','results': {'name': book.name, 'price': book.price},},json_dumps_params={'ensure_ascii':False})
class BookDetailView(View):
def get(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first()
l = []
l.append({'name': book_obj.name, 'price': book_obj.price})
return JsonResponse({'code': 100, 'msg': '查询一条成功', 'results': l})
def put(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
data = json.loads(request.body)
print(data)
models.Book.objects.filter(pk=pk).update(**data)
return JsonResponse({'code': 100, 'msg': '修改一条成功'})
else:
return JsonResponse({'code': 101, 'msg': '当前不存在此条数据'})
def delete(self,request,pk):
book_obj = models.Book.objects.filter(pk=pk).exists()
if book_obj:
models.Book.objects.filter(pk=pk).delete()
return JsonResponse({'code': 100, 'msg': '删除一条成功'})
else:
return JsonResponse({'code': 101, 'msg': '当前不存在此条数据'})
3.路由层urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
'''路由不一样,需要新写一个路由,可用转换器或者正则表达式,但使用转换器较多'''
path('books/' , views.BookDetailView.as_view()),
]
核心思想: 缩减编写api接口的代码
Django REST Framework是一个
建立在Django基础之上的Web应用开发框架
可以快速的开发REST API接口应用
在DjangoRestFramework中提供了序列化器Serialzier的定义 可以帮助我们简化序列化与反序列化的过程
还提供丰富的类视图、扩展类、视图集
来简化视图的编写工作DjangoRestFramework还提供了认证、权限、限流、过滤、分页、接口文档等
功能的支持 DjangoRestFramework提供了一个API 的Web可视化界面来方便查看测试接口
我们在写原生的前后端分离项目是使用的是Django的Web框架(只写接口 使用JsonResponse返回即可)
但是想让前后端分离更方便就可以用到DjangoRestFramework可以方便我们快速写出符合Restful规范的接口
官方文档:Home - Django REST framework
pip38 install djangorestframework
注意:
如果下载的Django版本过低(2.x)
的话,下载drf
会发现Django
版本太低不支持,然后会自动给你卸载重装最新版的Django
,但是如果Django的版本不低(3.x)
,下载drf
就不会有任何影响
首先需要
settings.py
中的INSTALLED_APPS
添加rest_framework应用
INSTALLED_APPS = [
'rest_framework',
]
注意
:如果不注册应用,在浏览器中就访问不了。注册了就可以看到一个页面展示。当然不注册也可以使用api测试工具来访问
没注册直接使用浏览器访问的效果
注册应用后使用浏览器访问的效果
没注册使用接口测试工具访问的效果
下面我用一个基于drf编写5个接口
1.先在models.py中创建一些字段
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
'''这里我就没去settings中修改默认数据库了,直接使用自带的sqlite3演示'''
记得创建好需要执行迁移命令:
python38 manage.py makemigrations
python38 manage.py migrate
2.创建序列化类
在应用下面创建一个
serializers.py
文件
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
序列化类(Serializer)将Model转换为序列化的JSON对象。
上面构建了BookSerializer的序列化类。序列化类看起来和django的Form很像。
3.创建视图views.py
from .serializer import BookSerializer
from rest_framework.viewsets import ModelViewSet
from app01 import models
class DrfBookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer
我们使用了ModelViewSet来快速构建一组view。由于背后实现了很多方法,这看起来有些像魔法。
4.配置路由urls.py
from django.urls import path
from app01 import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books',views.DrfBookView,'books')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls
因为我们使用的是ViewSet而不是view,所以我们可以通过简单地将ViewSet注册到Router来自动生成API的 URL conf。
可以发现,和Django程序相比,我们没有写template做前端的显示,而是写了序列化类提供API。前端可以分离出来,使用API来和后端通信。
'cbv写好后,路由配置如下'
-第一个参数是路径,第二个参数是试图函数的内存地址(视图类执行as_view这个类方法,把它执行完,
结果放在第二个参数上:我们猜执行完的结果是个函数内存地址)
path('books/', views.BookView.as_view()),
-去找as_view,去BookView类中找,找不到没有,则去父类中找View
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # BookView类实例化得到对象
return self.dispatch(request, *args, **kwargs) # BookView类的dispatch方法
'''如果BookView类的dispatch没有,则会去父类View中查找dispatch'''
return view
-当请求来了,路由匹配成功,会执行view(request)--->本质执行self.dispatch(request, *args, **kwargs)
-去View中找到了dispatch
def dispatch(self, request, *args, **kwargs):
# 请求方式转成小写,假设 get 请求,符合if条件
if request.method.lower() in self.http_method_names:
# 反射 getattr(对象,'字符串','默认值')
# self是BookView的对象
# handler 就是BookView类的get方法
handler = getattr(self, 'get', self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # get(request)
'''
小结:在View中找到dispatch后,会根据请求方式,
然后通过反射去视图类中的[BookView]反射出跟请求方式同名的方法,然后执行
'''
五个接口为:对数据库的增删改查
APIView
是基于Django
原生的View
编写接口的,是drf
提供的一个类(APIView)
,使用drf编写视图类,都是继承这个类及子类,APIView
本身就是继承了Django
原生的View
1.视图Views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
'drf的视图类比较规范,导入都有单独的模块'
class BookView(APIView):
def get(self, request):
book_list = models.Book.objects.all()
l = []
for book in book_list:
l.append({'name': book.name, 'price': book.price})
return Response({'code': 100, 'msg': '查询成功', 'results': l})
def post(self,request):
data = json.loads(request.body)
models.Book.objects.create(name=request.data.get('name'), price=request.data.get('price'))
return Response({'code': 100, 'msg': '添加成功','results': request.data})
class BookDetailView(APIView):
def get(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first()
l = []
l.append({'name': book_obj.name, 'price': book_obj.price})
return Response({'code': 100, 'msg': '查询一条成功', 'results': l})
def put(self, request, pk):
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
book_obj.name = request.data.get('name')
book_obj.price = request.data.get('price')
book_obj.save()
return Response({'code': 100, 'msg': '修改一条成功','results':request.data})
else:
return Response({'code': 101, 'msg': '当前不存在此条数据'})
def delete(self,request,pk):
book_obj = models.Book.objects.filter(pk=pk).exists()
if book_obj:
models.Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除一条成功'})
else:
return Response({'code': 101, 'msg': '当前不存在此条数据'})
2.路由urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/' , views.BookDetailView.as_view()),
]
从上述代码中可以看到继承APIView+Response和Django原生View区别到底在哪?
1.首先记住APIView类是drf提供的一个类,而drf是一个app,在django中三方模块都是一个个应用,
它注册app,rest_framework,就可以在浏览器中直接访问,drf自带的页面查看数据等。
而原生则无法查看,会直接报错,但是可以通过接口测试工具访问,但是仅只有纯json数据
2.在进行post请求的时候,原生View需要注释掉csrf中间件,而APIView无需注释
3.原生View传递数据时,如果是中文,需要声明ensure_ascii为False,而APIView无需
4.原生view使用form-data/urlencoded用获取json格式的不一样,需要从request.body中按照所需切割,比较麻烦,
而APIView内部对数据进行了封装,直接使用request.data可自行判断是否是那种编码格式然后进行自行转换好,无需我们
进行操作
首先drf是一个Django第三方的App 它只适用于Django 如果使用到别的框架是使用不了的
安装drf之后就可以导入一个视图累APIView 所以要使用drf写视图类 都要继承APIView以及其子类
这里仅解读几个重要的源码
首先在路由中:path('books/', views.BookView.as_view()),当请求来了
然后会执行as_view(),因为是继承着APIView所以会进入到APIView中执行它的as_view,
而APIView的as_view其实执行结果和Django原生View的as_view是一样的,不过去除了csrf认证
class APIView(View):
@classmethod
def as_view(cls, **initkwargs):
'''
如果视图类有queryset属性,且其类型为models.query.QuerySet,则设置一个函数force_evaluation
这个函数用于防止直接评估queryset,因为结果会被缓存并在多个请求之间重复使用
'''
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
'''
这里调用了父类的as_view方法,父类是Django原生的View
然后把自己的参数传递了进去,并返回被csrf_exempt装饰的视图,这个csrf会把所有的请求csrf检验认证去掉
'''
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
'''
csrf_exempt是一个装饰器,用于豁免csrf验证
相当于在所有的方法上加上了这个装饰器
'''
return csrf_exempt(view)
'''
总结:当路由匹配成功后,会执行APIView父类的as_view,并且会先执行csrf_exempt(View)(request)
然后按照正常执行Django原生的as_view方法,然后会执行它的view(request),最终会返回一个
return self.dispatch(request, *args, **kwargs),它会从视图类中寻找,发现没有,
因为视图类继承的是APIView,所以会优先从APIview中寻找是否有dispatch这个方法,结果找到了
'''
'dispatch方法用于处理传入的请求'
def dispatch(self, request, *args, **kwargs):
'保存参数'
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
'''
这里把原来的request传入到self.initialize_request对象中
然后会执行def initialize_request方法,最后它返回了一个Response(reqeust)
它又把这个原来的request传入进去了,然后实例化对象,然后对象加括号会调用Response的初始化方法
下面就是它的__init__方法,我们也对其进行解读
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
这里它把传入过来的原request放到这个self._request中,这里的self已经不是视图类了,
因为这个Request类没有继承任何一个类,它就是它自己,所以这个self是Request
self._request = request
# 指定解析器、身份验证器、内容协商器的参数,默认为 None 或空元组
self.parsers = parsers or ()
self.authenticators = authenticators or ()
self.negotiator = negotiator or self._default_negotiator()
self.parser_context = parser_context
# 用于保存请求数据的属性,初始值为 Empty(可能是一个自定义的占位符类)
self._data = Empty
self._files = Empty
self._full_data = Empty
self._content_type = Empty
self._stream = Empty
'''
'''
从上面一路追源码可以看到,此时这里的self.request已经不是最开始的request了,变成了DRF提供的Request类的对象了
而是initialize_request经过一系列操作得到的新的request了,然后此处的self则还是视图类,
所以后续视图类的方法中,可以直接使用self.request取出它,视图类的request=新的request了
'''
self.request = request
try:
'执行initial方法,这里执行了三大认证,认证/频率/权限'
self.initial(request, *args, **kwargs)
'通过反射方法,去视图类中执行跟请求方式同名的方法'
# 这个就跟原来的那个View类的dispatch 判断当前是否拥有八大方法如果有则执行
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
'因为这里得到同名的方法后传入的也是新的Request类对象了,那么视图类方法的传入的request也是新的request'
response = handler(request, *args, **kwargs)
except Exception as exc:
'调用处理方法,如果执行三大认证或视图类方法中出现了错误,都会捕获异常,统一处理'
response = self.handle_exception(exc)
'最终处理响应'
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
只要继承APIView,以后方法中的request都变成rest_framework.request.Request的对象了(可以使用type方法查看一下)
但是跟Django原生的用起来是一模一样的,仅只是添加新的功能了,相当于装饰器一样
原生的Django request使用type方法是:django.core.handlers.wsgi.WSGIRequest类的对象
'''
总结:APIView的执行流程:
1 只要继承APIView都没有csrf的认证了
2 以后视图类方法中得request对象,变成了新的request,
它是rest_framework.request.Request 的对象了,但是用起来跟之前一样
3.把新的request对象,同时放到了 视图类的对象中 self.request = request
后续从视图类中可以直接通过 self.request取出来
4 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
5 如果在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理(异常捕获是全局异常捕获)
'''
'在执行视图类的方法之前干了一些事'
-去除csrf
-包装新的requet
-在视图类中加入了 self.request
-执行三大认证
'在执行视图类的方法之后干了一些事'
-处理全局异常