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&region=%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 处理了全局异常

 

posted @ 2023-08-28 16:36  Maverick-Lucky  阅读(36)  评论(0)    收藏  举报