一、DRF简介与安装
1.简介
drf:djangorestframework,是一个基于django的包,相当于我们自己的app,使用前需要在配置文件中注册
作用:更快速在django框架上的写接口
2.安装
命令行中:
pip3 install djangorestframework
pycharm中:
在settings-搜素框输入python interpreter-点击左侧的加号-搜索djangorestframework,安装最新版本即可
二、restful规范
1 Representational State Transfer:表征性状态转移
2 Web API接口的设计风格,尤其适用于前后端分离的应用模式中
3 与语言,平台无关,任何框架都可以写出符合restful规范的api接口
4 规范:
规范:接口地址使用复数名词,比如获取图书相关,用books,而不是get_books,对于获取的资源操作,由请求方式决定,比如
对于地址https://api.baidu.com/books,若get请求,返回所有图书信息,如果是post请求,就添加一本新书。正常情况下,都需要返回
状态码来标识此次请求的状态等
完整的十条规范:
-1 数据的安全保障:url链接一般都采用https协议进行传输
-2 接口特征表现:api关键字标识
-https://api.baidu.com/books/
-https://www.baidu.com/api/books/
-3 多版本共存:url链接中标识接口版本
-https://api.baidu.com/v1/books/
-https://api.baidu.com/v2/books/
-4 数据即是资源,均使用名词(可复数)***********
-接口一般都是完成前后台数据的交互,交互的数据我们称之为资源
-一般提倡用资源的复数形式,不要使用动词
-查询所有图书
-https://api.baidu.com/books/
-https://api.baidu.com/get_all_books/ # 错误示范
-https://api.baidu.com/delete-user # 错误的示范
-https://api.baidu.com/user # 删除用户的示例:疑问:到底是删还是查?
-5 资源操作由请求方式决定:
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的书
-6 过滤,通过在url上传参的形式传递搜索条件
https://api.example.com/v1/zoos?limit=10 :指定返回记录的数量
https://api.example.com/v1/zoos?offset=10&limit=3:指定返回记录的开始位置
https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
-7 响应状态码
-返回数据中带状态码
-{'code':100}
-8 返回结果中带错误信息
-{'code':100,'msg':'因为xx原因失败'}
-9 返回结果,该符合以下规范
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象(字典)
POST /collection:返回新生成的资源对象 (新增后的对象字典)
PUT /collection/resource:返回完整的资源对象 (修改后的对象字典)
PATCH /collection/resource:返回完整的资源对象 (修改后的对象字典)
DELETE /collection/resource:返回一个空文档 ()
-10 返回的数据中带链接地址
-查询id为1的图书接口,返回结果示例
{'code':100,
'msg':'成功',
'result':
{'title':'金梅',
'price':12.3,
'publish':'https://127.0.0.1/api/v1/publish/3'
}
}
三、APIview源码分析
APIview是drf中基础的类,他继承了我们django的View类,且对我们的request请求做了封装,对于使用来说,和之前的使用一样,并且还多了一些方法,其实很想一个装饰器,并且这种做法也是非常符合面向对象封装的思路。
1.步骤一
当请求进入我们的项目,路由匹配成功后,会执行类的as_view方法,很明显drf重写了这个方法
APIview的as_view
-利用super().as_view(**initkwargs),所以内部还是执行了View的闭包函数view
-把cls和initkwargs设置为这个对象的属性
-禁用掉了csrf
2.步骤二
由View类中的as_view方法可知我们这个闭包函数他对调用对象的dispatch方法。
此时因为我们调用的类是APIView,所以先在自己的对象中找。
很明显正常情况下我们不会重写dispatch方法,那么就会优先去APIView这个类中找这个方法
原生View类中过的as_view中的闭包函数view
-本质执行了self.dispatch(request, *args, **kwargs),此时执行的是APIView的dispatch
DRF的Request类的对象,内部有request._request,才是原生request
上面第一个红色箭头的语句,调用了initialize_request,很明显对象中没有,又到APIView中找,我们找到了源码如下
四、Request源码分析
通过上面的源码分析,我们知道了在请求一进到路由后,由as_view开始,连续出发了一系列的方法,上一步分析到了在dispatch中,因为调用了initialize_request,其又用Request类实例化对象返回,那么我们进入Request类中分析,首先是构造方法。通过下面的部分代码可知,进行到这一步的时候,原生的WSGI类下的request,变成了对象的_request属性。
虽然request已经不是之前的对象了,但是我们依然通过点来获取之前的属性,比如,request.method,所以我们断定Request类中重写了getattr魔术方法
Request类
-request._request:原生request
-request.data : post请求提交的数据(urlencoded,json,formdata)
-request.user :不是原生的user
-request.query_params :原生的request.GET,为了遵循restful规范
-requset.FILES :新的
-重写了__getattr__,新的request.原来所有的属性和方法,都能直接拿到,如上图