drf入门

drf入门

目录

  • 前后端开发模式
  • API接口
  • 接口测试工具
  • restful规范
  • 序列化反序列化
  • djangorestframework快速使用
  • APIView 基本使用
  • APIView 源码分析
  • Request 类源码分析

前后端开发模式

在web开发中前后端有两种开发模式,分别是前后端混合开发和前后端分离开发

就目前形势来讲,前后端分离开发已成大势

前后端混合开发

前后端不分离

  • 前后端混合开发-----》模板,使用模板语法渲染模板

    前后端混合开发需要后端人员通过前端写好的html页面来套模板语法完成后端代码的编写

  • 前端后台管理模板

    layui+jquery

    bootstrap+jquery

前后端分离开发

前后端分离

前后端分离只需要前端写好前端的代码,后端完成后端的代码,分别通过各自的接口测试,最后组合起来即可

  • 后端

    后端人员只负责写接口(API接口),使用postman接口测试工具测试

  • 前端

    前端人员只负责写前端,写的过程中使用mock数据

  • 总合

    将前后端联调项目,最后交付于测试

API接口

  • 什么是API接口

    ​ 通过网络,规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介

  • Web API接口的四大特点

    ①url:长得像返回数据的url链接

    https://api.map.baidu.com/place/v2/search

    ②请求方式:get、post、put、patch、delete

    ​ 采用get方式请求上方接口

    ③请求参数:json或xml格式的key-value类型数据

        ak:6E823f587c95f0148c19993539b99295
        region:上海
        query:肯德基
        output:json
    

    ④响应结果:json或xml格式的数据

    ​ 上方请求参数的output参数值决定了响应数据的格式

接口测试工具postman

Postman是一款接口调试工具,是一款免费的可视化软件,同时支持各种操作系统平台,是测试接口的首选工具。

  • 用途

    API接口写好,后端人员要测试,不可能在浏览器里测试,故而使用接口测试工具测试

  • 接口测试工具postman本质

    ​ 模拟发送http请求

  • 接口测试软件

    ​ 接口测试软件有很多,例如postwoman,但最常用的接口测试软件还是postman

  • 下载安装

    官方下载:https://www.postman.com/downloads/

    安装:一路到底,傻瓜式安装

  • 工作面板

restful规范

REST全称是Representational State Transfer,中文意思是表述:表征性状态转移

RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中

restful规范有10点---》规范,公司有自己的风格规范

1.数据的安全保障

  • url链接一般都采用https协议进行传输

    为了保证数据安全使用https协议传输

2.接口特征表现

  • 用api关键字标识接口url

    https://api.baidu.com
    https://www.baidu.com/api
    

    该请求url链接是完成前后台数据交互的

3.多数据版本共存

一个接口可能有多个版本

例如:
https://api.baidu.com/v1
https://api.baidu.com/v2

url链接中的v1、v2就是不同数据版本的体现(只有在一种数据资源有多版本情况下)

4.数据即是资源,均使用名词(可复数)

  • 接口一般都是完成前后台数据的交互,交互的数据我们称之为资源

    https://api.baidu.com/users
    https://api.baidu.com/books
    https://api.baidu.com/book
    

    一般提倡用资源的复数形式,在url链接中奖励不要出现操作资源的动词

  • 特殊的接口可以出现动词,因为这些接口一般没有一个明确的资源,或是动词就是接口的核心含义

    https://api.baidu.com/place/search
    https://api.baidu.com/login
    

5.资源操作由请求方式决定

  • 操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作

    ​ -获取数据:get请求
    ​ -删除数据:delete请求
    ​ -新增数据:post请求
    ​ -修改数据:put,patch请求
    请求地址一样,通过请求方式决定对资源进行什么操作

6.过滤

通过在url上传参的形式传递搜索条件

https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
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.响应状态码

  • http状态码:

    ① 1xx:表示请求正在处理,一般看不到
    ② 2xx: 表示请求处理成功,

    ​ 200:成功请求

    ​ 201:创建成功

    ③ 3xx: 重定向

    ​ 301: 永久重定向

    ​ 302: 临时重定向

    ④ 4xx: 客户端错误

    ​ 403 :请求无权限

    ​ 404 :请求路径不存在

    ⑤ 5xx :服务端错误

    ​ 500: 服务器异常

8.错误处理,应返回错误信息,error当做key

{code:100,msg:成功}

9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范

GET /collection:返回资源对象的列表(数组)[{},{}]
GET /collection/resource:返回单个资源对象 {}
POST /collection:返回新生成的资源对象 {}
PUT /collection/resource:返回完整的资源对象 {}
PATCH /collection/resource:返回完整的资源对象 {}
DELETE /collection/resource:返回一个空文档

-获取所有:{code:100,msg:成功,data:[{name:三体,price:99},{name:西游记,price:88}]}
-获取单条:{code:100,msg:成功,data:{name:三体,price:99}}
-新增数据:{code:100,msg:新增成功,data:{name:西游记,price:99}}
-修改数据:{code:100,msg:修改成功,data:{name:西游记v2版本,price:99}}
-删除数据:{code:100,msg:删除成功}

10.响应中带链接

# Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么
{
  	"status": 0,
  	"msg": "ok",
  	"results":[
        {
            "name":"肯德基(罗餐厅)",
            "img": "https://image.baidu.com/kfc/001.png"
        }
      	...
		]
}

序列化、反序列化

API接口开发最核心,最常见的一个过程就是序列化。所谓序列化就是把数据转换格式

  • 序列化的两个阶段

    • 序列化

      ​ 把我们识别的数据转换成指定的格式提供给别人

      -例如:我们在django中获取到的数据默认是模型对象(queryset),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

    • 反序列化

      ​ 把别人提供的数据转换/还原成我们需要的格式

django Rest_Framework快速使用

  • 核心思想

    ​ 缩减编写api接口的代码

  • 什么是 django Rest_Framework

    ​ Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。

    ​ 在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作

    ​ REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。

  • 特点

    ​ ①提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化

    ​ ②提供了丰富的类视图、Mixin扩展类,简化视图的编写

    ​ ③丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要

    ​ ④多种身份认证和权限认证方式的支持

    ​ ⑤内置了限流系统

    ​ ⑥直观的API web界面

    ​ ⑦可扩展性,插件丰富

  • 使用django这个web框架,开发前后端分离项目(模板渲染),只写接口

    ①使用JsonResponse返回即可---》原生django

    ②djangorestframework方便咱们快速写出符合restful规范的接口

  • 写接口 的五种类型

    ①获取所有 get

    ②获取单个 get

    ③新增一条 post

    ④修改一条 put/patch

    ⑤删除一条 delete

对于表来说,快速实现五个接口

  • 安装drf

    ​ pip3 install djangorestframework

  • urls.py

    from django.contrib import admin
    from django.urls import path
    from rest_framework.routers import SimpleRouter
    from app01 import views
    
    router = SimpleRouter()
    router.register('books', views.BookView)
    urlpatterns = [
        path('admin/', admin.site.urls),
    ]
    urlpatterns += router.urls
    
  • views.py

    from .models import Book
    from rest_framework.viewsets import ModelViewSet
    from .serializer import BookSerializer
    
    
    class BookView(ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
  • models.py

    from django.db import models
    
    
    class Book(models.Model):
        name = models.CharField(max_length=32)
        price = models.CharField(max_length=32)
        publish = models.CharField(max_length=32)
    
  • serializer.py

    from rest_framework import serializers
    from .models import Book
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = '__all__'
    
  • 通过postman测试

cbv源码分析

  • url路由

    path('test/', views.TestView.as_view()),
    

    第一个参数是路径,第二个参数是试图函数的内存地址(视图类执行as_view这个类方法,把它执行完,结果放在第二个参数上:我们猜执行完的结果是个函数内存地址)

  • 查看as_view()源码

    找as_view,去TestView类中找,找不到,没有,去父类中找View
    
    @classonlymethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
            return self.dispatch(request, *args, **kwargs)
        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是TestView的对象
                    # handler 就是TestView类的get方法
                    handler = getattr(self, 'get', self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
                return handler(request, *args, **kwargs)  # get(request)
    

APIView基本使用

drf 是一个第三方的app,只能再django上使用

  • 安装drf

    ​ pip3 install djangorestframework

    安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类

  • 在后端上获取所有的数据对象接口

使用View+JsonResponse写

class BookView(View):
    def get(self, request):
        print(type(request))
        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False})  # 只能序列化字典和列表,

使用APIView+drf的Response写

  • 使用 APIView+drf的Response 前需要注册 rest_framework 这个app
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request


class BookView(APIView):  # APIView继承自django的View
    def get(self, request):
        
        print(request._request)
        print(type(request._request)) 

        book_list = Book.objects.all()
        # book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
        res_list = []
        for book in book_list:
            res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
        return Response(res_list)
    

APIView源码分析

视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程

  • url路由

    path('test/', views.TestView.as_view()),
    

    第一个参数是路径,第二个参数是试图函数的内存地址(视图类执行as_view这个类方法,把它执行完,结果放在第二个参数上:我们猜执行完的结果是个函数内存地址)

  • 先找视图类的as_view,即【APIView_view】,自身没有as_view,再找其父类APIview,查看APIView源代码

    @classmethod
    def as_view(cls, **initkwargs):
        # 又调用了父类(View)的as_view
        view = super().as_view(**initkwargs)
        return csrf_exempt(view)
    

    APIView中也没有as_view,利用super方法调用了其父类(view)中的as_view

    csrf_exempt(view): 返回这个 就相当于往后的请求都不用再做csrf的校验了,就相当于再函数上加了装饰器

    @csrf_exempt
    def index(request):
        pass
    

    本质等同于 index=csrf_exempt(index)

  • 请求来了,路由匹配成功会执行, View类的as_view类方法内的view闭包函数(但是没有了csrf认证),

    def view(request,*args, ** kwargs):
        
        return self.dispatch(request,*args, ** kwargs)
    

    ​ 真正的执行,执行self.dispatch就是APIView的dispatch

  • APIView的dispatch

     def dispatch(self, request, *args, **kwargs):
            # 参数的request是原来的django原生的request
            # 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
            request = self.initialize_request(request, *args, **kwargs)
            # self 是视图类的对象,视图类对象.request=request 新的request
            self.request = request
            try:
                # 执行了认证,频率,权限 [不读]
                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
                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都没有csrf的认证了

    ②以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了

    ③执行视图类的方法之前,执行了3大认证(认证,权限,频率)

    ④在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理

Request类源码分析

  • 视图类中使用的request对象,已经变成了drf提供的Request类的对象了

    • 原生djagno 的request是这个类的对象

      ​ 这个类 : django.core.handlers.wsgi.WSGIRequest

    • drf的request是这个类的对象:

      ​ 这个类 : rest_framework.request.Request

  • request已经不是原来的request了,还能像原来的request一样使用吗?

    ​ 虽然request已经不是原先的request了,但用起来与之前一样

    print(request.method)  # get
    print(request.path)  # /books/
    print(request.GET)   # 原来的get请求提交的参数
    print(request.POST)  # 原来post请求提交的参数
    
  • Request的源码分析

    查看 rest_framework.request.Request 导入后的源码

    • 类中有个魔法方法: __ getattr__ 对象.属性,属性不存在会触发它的执行

      def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来
          try:
              #反射:根据字符串获取属性或方法,self._request 是原来的request
              return getattr(self._request, attr)
          except AttributeError:
              return self.__getattribute__(attr)
      
    • 以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)

    • 新的request内部有个老的request,就是 request._request

    • data 是个方法,被property装饰了,变成了数据属性用

      ​ ①以后body体中提交的数据,都从这里取(request.POST)

      ​ ②urlencoded,form-data:提交的数据在request.POST中

      ​ ③json格式提交的数据,在requets.POST中没有,它在request.body中

      ​ ④现在无论那种格式,都从request.data中取

    • query_params

      ​ get请求提交的参数,等同于request._request.GET 或 request.GET

    • 其他

      ​ 取文件也是从request.FILES中取,跟之前一样

  • 什么是魔法方法?

    ①在类中只要以__ 开头,__ 结尾的都称之为魔法方法

    ②这种方法不需要手动调用,某种情况会自动触发

    ③学过的魔法方法:

    ​ __ init__ , 类加括号 自动触发执行

    ​ __ str__ , 打印对象的时候触发执行

    ​ __ call__, 对象加括号的时候,自动触发执行

    ​ __ getattr__ 对象.属性,在属性不存在时会触发它的执行

  • 总结

    • 验证 原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据

    • request.data 有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典

posted @   Nirvana*  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示