drf-入门规范
一、Web开发模式
Web开发模式主要有两种:
1. 前后端混合开发模式 :一般老项目是使用的这种模式
-模版语法:dtl:django tmeplate language
-模版渲染:在后端完成

2. 前后端分离开发模式:新项目
- 后端专门的后端:API接口
- 前端专门的前端:html,css,js---》ajax---》后端交互---》通过调用api接口返回数据---》字符串---》转成js的数组,对象,字符串..

二、API接口
为了在团队内部形成共识,防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本
API接口:
前后台信息交互的媒介,通过网络,规定了前后台信息交互规则的url链接。
比如:
-https://www.baidu.com/books/--->json 格式数据---》这个就是一个接口
-https://www.cnblogs.com/liuqingzheng/articles/17400599.html---》而这个是url链接,直接返回界面的
url和接口的区别:Web API接口和一般的url链接还是有区别的 ,Web、API接口有以下四大特点:
1.有 url:长得像返回数据的url链接
2. 有请求方式:get 、post、put 、patch、delete
3. 请求参数:json或xml格式的key:value类型的数据
比如:
ak:6E823f587c95f0148c19993539b99295
region:上海
query:肯德基
output:json
4. 有响应结果:json或xml格式的数据
https://api.map.baidu.com/place/v2/searchak=6E823f587c95f0148c19993539b99295®ion=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=json
# 典型的API接口长这样
-url地址
-有请求方式
-携带参数
-返回格式是json,xml
三、接口测试工具Postman
接口测试工具有很多:
-postman:浏览器插件---》做成了软件免费---》收费
-apifox:Postman + Swagger + Mock + JMeter
-postwoman
下载地址:https://www.postman.com/
(双击安装就好了)
使用:





前后端传输数据的编码格式---urlencoded,formdata, json这三种格式的详解
form表单&ajax,都默认的urlencode编码格式:
-urlencoded: body体中 :username=lqz&password=123
django后端,针对符合urlencoded编码格式的数据,都会自动,帮你解析封装到request.POST中,
form-data:
body中格式固定:数据部分和文件部分--》request.POST能取出数据,取不出文件,文件都是从
'----------------------------789048583058585187025897\r\nContent-Disposition: form-data; name="username"\r\n\r\nlqz\r\n文件二进制
数据解析封装到request.POST,而将文件解析到request.FILES中。
json格式:
-json: body体中 :{"username":"lqz","password":"123"}
django后端不会帮你处理json格式数据需要你自己去request.body获取并处理
在request.body里面取出来的是bytes类型的,需要自己手动解码,反序列化。
四、restful规范
1. 前后端分离要写接口:api接口
2. restful规范是什么,如何来的?
- restful规范:一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中的规范
- Roy Fielding的博士论文提出的
3. 以后写接口,大致都要遵循一个规范:restful规范
1. 数据的安全保障:url链接一般都采用https协议进行传输,https比http安全
2. 接口特征表现:url中带api标识
比如:
- https://api.baidu.com/books/
- https://www.baidu.com/api/books/
3. 多数据版本共存:url中带版本信息
- https://api.baidu.com/v1/books
- https://ww.baidu.com/api/v2/books
4. 数据即是资源,均使用名词(可复数): 前后台交互,交互的数据称之为资源,url尽量使用名字
- https://127.0.0.1/api/v1/books/ 表示对图书操作:增加,删除,查询,修改,都用这一个地址
5. 资源操作由请求方式决定
- get请求:获取数据(获取所有,获取单条)
- https://api.baidu.com/books - get请求:获取所有书
- https://api.baidu.com/books/1 - get请求:获取主键为1的书
- post请求:新增数据
- https://api.baidu.com/books - post请求:新增一本书书
- put请求:修改数据
- https://api.baidu.com/books/1 - put请求:整体修改主键为1的书
- delete请求:删除数据
- https://api.baidu.com/books/1 - delete请求:删除主键为1的书
6. 请求地址中带过滤条件:只针对于搜索所有的接口
7. 两层响应状态码
- http响应状态码:1xx,2xx,3xx,4xx,5xx
-1xx表示请求正在处理---》前端一般看不到
-2xx 表示请求处理成功--》经常看到
-201和200有什么区别
-3xx:重定向
-301和302
-4xx:客户端错误
-404和403 和 405
-5xx:服务端出错
-成功都返回200,而在响应体中带的状态码--->code :不同公司就不一样
8. 响应中带错误信息:{"code": 101,"msg": "用户名或密码错误"}
9. 不同的操作,返回格式符号如下标准:
GET/collection:返回资源对象的列表(数组):[{name:西游记,price:19},{name:三国,price:19}]
GET /collection/resource:返回单个资源对象 :{name:三国,price:19}
POST /collection:返回新生成的资源对象:{name:三国,price:19}
PUT /collection/resource:返回完整的资源对象:{name:三国演绎,price:19}
DELETE /collection/resource:返回一个空文档
10. 响应中带链接
五、序列化反序列化
序列化:数据转换格式,分为两个阶段:
- 序列化:把我们标识的数据转成指定的格式提供给别人
- 反序列化:把别人提供的数据转换/还原成我们需要的格式
序列化:把我们标识的数据转换成指定的格式提供给别人
例如:我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。
反序列化:把别人提供的数据转换/还原成我们需要的格式
例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中
六、drf安装和快速使用
Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。
什么是drf?
drf 是一个第三方模块。只能用在django中,可以帮助我们快速编写符合restful规范的接口。
核心思想: 缩减编写api接口的代码。
基于django编写符合restful规范的接口:
以Book表为例,写它的5个接口
-1 查询所有(get)
-2 新增一条(post)
-3 修改一条(put)
- put 请求如果是urlencoded编码,从request.POST中取不到值,需要自己从request.body中取:username=lqz&password=123,需要自己转为字典格式的数据
-4 删除一条(delete)
-5 查询一条(get)
djangorestframework: drf,django的一个第三app---》方便我们快速实现符合restful规范的接口
使用步骤:
1 安装模块
- django 是2版本,用不了drf最新(适当降版本),他会卸载django---》装最新4.x
- djagno 3.1.12 可以使用drf最新
安装版本: -django:3.1.12 -drf:3.14.0
2 在app中注册
INSTALLED_APPS = [
'rest_framework', # 一定不要忘了加 ,
]
3 写路由
from rest_framework.routers import DefaultRouter
router = DefaultRouter() # 可以处理视图的路由器
router.register('books', BookView, 'books')
urlpatterns += router.urls # 将路由器中的所以路由信息追到到django的路由列表中
4 写视图类
from rest_framework.viewsets import ModelViewSet
from .serializer import BookSerializer
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
- queryset 指明该视图集在查询数据时使用的查询集
- serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器
5 写序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
- model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
- fields 指明该序列化器包含模型类中的哪些字段,’all‘指明包含所有字段
补充:
# 函数和方法
-函数:使用def关键字定义的函数,有几个参数,就要传几个参数,不能多,不能少-----》按位置传,按关键字传
-方法:定义在类内部,可以自动传值的函数称之为方法---》绑定给对象的方法(对象方法)---》绑定给类的方法(类 方法)
-对象方法:对象来调用,自动把对象传入,
-类也可以调用,但是类来调用,就变成了普通函数,有几个值,就要传几个值
-类方法:类来调用,自动把类传入
-对象也可以调用,内部会取到对象的类,自动传入,它也是方法
七 CBV源码分析
CBV:基于类的视图,使用类来进行编写,在类中写跟请求方式同名的方法,请求过来,什么请求,就会执行跟请求方式同名的方法。
执行流程:
- 请求来了,然后做路由匹配:如果是books/匹配上了(path('books/',BookView.as_view())的内部就会执行并将实参request传入),执行BookView.as_view()(request)
BookView.as_view()(request):先执行as_view()方法,BookView中没有as_view方法,就从继承的父类View中找as_view方法,然后执行里面的view闭包函数(实例化BookView类得到了一个self对象),闭包函数调用了self.dispatch---->是BookView的,于是去了View的----》通过反射获取跟请求方式同名的方法---》然后执行,把request传入
View.as_view的源码分析:
# 执行:BookView.as_view()(request)---》本质是执行 View中as_view内部的view方法,传入了request @classonlymethod def as_view(cls, **initkwargs): # cls:是BookView,是调用类的绑定方法,会将自己作为第一个参数传给 cls # 是一个闭包函数 def view(request, *args, **kwargs): self = cls(**initkwargs) # cls:BookView,self就是BookView类实例化得到的对象 return self.dispatch(request, *args, **kwargs) # self.dispatch:调用对象的绑定方法:dispath,BookView中找不到,就去父类View中找 return view # 执行:BookView.as_view()(request)---》本质是执行 View中as_view内部的view方法,传入了reuqest----》在执行View的dispatch方法,传入了request
View.dispatch的源码分析
def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: # 判断请求方式是否在那个固定的列表中[get, post...]---> # 反射:通过字符串 动态的 操作对象的属性或方法 # 假设是get请求---》去BookView中取出 get方法赋值给handler handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed # 执行handler加括号,传入了request # 本质是执行 get(request) return handler(request, *args, **kwargs)
执行流程总结:
-路由匹配成功---》配置在路由上的第二个参:执行函数内存地址(request)---》执行view(request)
--->执行了self.dispatch--->BookView没有--》找到了父类View---》dispatch---》
handler = getattr(self, 'get')
return handler(request, *args, **kwargs)
八、APIView执行流程分析
1. 基于drf的APIView写接口
1. 使用drf ,以后都写CBV,继承一个视图类(drf提供的APIView)
2. APIView 继承了django的View
3. 补充:以下的三个View是一样的
from django.views import View
from django.views.generic import View
from django.views.generic.base import View
4. 继承APIView写cbv,执行起来和之前的效果一样,但是内部发生了非常大的改变
步骤:
1. 写视图类
from rest_framework.views import APIView class PublishView(APIView): def get(self,request): resturn JsonResponse({'code': 100})
2. 配置路由
path('publish/', PublishView.as_view()),
2. APIView的执行流程分析
执行流程分析:
-请求来了---》执行PublishView.as_view()(request)--->PublishView类没有as_view---》找父类---》APIView的as_view
-APIView的as_view---》本质在禁用csrf认证
@classmethod def as_view(cls, **initkwargs): # 调用父类的as_view得到返回值赋值给view---》django的View的as_view【看过】---》返回View的as_view的闭包函数 view view = super().as_view(**initkwargs) # 现在这个view就是原来看的View的as_view的view # 去除了csrf认证----》局部禁用csrf---》在视图函数上加 装饰器csrf_exempt # 加了装饰器的本质: 被装饰的函数=装饰器(被装饰的函数) return csrf_exempt(view)

-PublishView.as_view()(request)--》执行了禁用掉csrf的View的as_view的view---》self.dispath--->APIView的dispath
def dispatch(self, request, *args, **kwargs): # 1 包装了新的request对象 request = self.initialize_request(request, *args, **kwargs) # 把新的request,赋值给了 self.request # self 是 PublishView的对象 self.request = request try: # 2 执行了3大认证 self.initial(request, *args, **kwargs) ######开始### 跟之前View的dispath是一样的---》根据请求方式执行类中同名方法 ###执行视图类的方法 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 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
1. 包装新的request
- request.data:前端传入的数据(post,put,编码格式)--->写到在请求体中的数据,都用
- 老request中有 request.GET 新的使用request.query_params 充当 本质就是request._request.GET
- 其他的所有属性方法,用起来跟之前一样
2. 三大认证(认证、频率、权限): self.initial(request, *args, **kwargs)
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)

3.处理了全局异常,统一处理了
APIView 执行流程总结:
路由匹配成功---》BookView.as_view()--->APIView的as_view配置在路由上的第二个参:执行函数内存地址(request)---》执行View的view(request)--》但是它去除了csrf认证---》dispatch---》APIView的dispatch---》
在dispatch中做了这几件事:
1 包装了新的request---》视图类的方法中的request是新的
2 执行三大认证
3 处理了全局异常
浙公网安备 33010602011771号