一:DRF入门

简介

这里是 我们 前后端分离 开发模式的开始-----> 后端的开始。
django-rest-framework:DRF,是Django的一个app,可以更快地在Django框架上编写接口(不用也可以写符合规范的接口)。

DRF官网感兴趣的看看

DRF需要以下依赖:

  • Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
  • Django (1.10, 1.11, 2.0)

DRF是以Django扩展应用的方式提供的,所以我们可以直接利用已有的Django环境而无需从新创建。(若没有Django环境,需要先创建环境安装Django)

安装

pip3 install djangorestframework

需要注意的点:

在安装djangorestframework的时候,有时会自动把django升级到最新版本,如果需要指定的django版本,再安装即可

API接口

  • 规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介。

为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。

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

Web API接口和一般的url链接还是有区别的,Web API接口简单概括有下面四大特点

  • url:长得像返回数据的url链接
  • 请求方式:get、post、put、patch、delete
  • 采用get方式请求上方接口
  • 请求参数:json或xml格式的key-value类型数据
  • ak:6E823f587c95f0148c19993539b99295
  • region:上海
  • query:肯德基
  • output:json
  • 响应结果:json或xml格式的数据
# xml格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295®ion=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=xml
#json格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295®ion=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=json
{
    "status":0,
  	"message":"ok",
    "results":[
        {
            "name":"肯德基(罗餐厅)",
            "location":{
                "lat":31.415354,
                "lng":121.357339
            },
            "address":"月罗路2380号",
            "province":"上海市",
            "city":"上海市",
            "area":"宝山区",
            "street_id":"339ed41ae1d6dc320a5cb37c",
            "telephone":"(021)56761006",
            "detail":1,
            "uid":"339ed41ae1d6dc320a5cb37c"
        }
      	...
		]
}

目前市面上大部分公司开发人员使用的接口服务架构主要有:restful、rpc,soap。

rpc:翻译成中文:远程过程调用[远程服务调用]

优点:

不需要管当前操作是什么http请求,也不需要操作url地址的编写,对接简单

缺点:

接口多了,对应函数名和参数就多了,前端在请求api接口时,就会比较难找.容易出现重复的接口

把后端所有的数据/文件都看成资源

那么接口请求数据,本质上来说就是 对资源的操作

web项目中操作资源,无非就是增删查改,所以要求在地址栏中声明要操作的资源是什么,然后通过http请求动词来说明对资源进行哪一种操作

POST http://www.renran.cn/api/students/   添加学生数据

GET    http://www.renran.cn/api/students/   获取所有学生

DELETE http://www.renran.cn/api/students/<pk>/   删除id=pk的一个学生

PUT   http://www.renran.cn/api/students/<pk>/       修改一个学生的全部信息 [id,name,sex,age,]

PATCH  http://www.renran.cn/api/students/<pk>/    修改一个学生的部分信息[age]
优点:

维护开发简单,可以保证后期的开发不会出现太多重复接口

缺点:

有部分接口不会有明确的增删查改这种区分的,所以会出现一些不伦不类的接口。

会因为这些语义不明,不伦不类的接口导致后期的维护成本上升。

因为restful把对于资源的操作都理解成了增删查改,建议使用http,所以restful接口天生局限于web开发。

接口文档

  • 可以手动写(公司有平台,录到平台里,)
  • 自动生成(coreapi,swagger)

二:RESTful规范

简介

REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征性状态转移)。 它首次出现在2000年Roy Fielding的博士论文中。

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

这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。

而对于数据资源分别使用POST、DELETE、GET、UPDATE等请求动作来表达对数据的增删查改。

它与语言、平台无关,任何框架都可以写出符合RESTful规范的API接口

10条规范

1.数据的安全保障

URL链接一般都采用HTTP协议进行传输

HTTPS协议 = HTTP协议 + SSL证书

HTTPS协议传输,可以提高数据交互过程中的安全性; API与用户的通信协议,总是使用HTTPs协议。

2.接口特征表现

URL中,有API的关键字标识

例:
https://api.baidu.com/books/  # 尽量将API部署在专用域名(会存在跨域问题)
https://www.baidu.com/api/books/  # API很简单

3. 多数据版本共存

URL中 ,标识接口的版本; 请求地址中带版本,或者在请求头中。

https://www.baidu.com/v1/books/
https://www.baidu.com/v2/books/

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

  • 接口一般都是前后台数据的交互,交互的数据 我们称之为资源
  • 一般提成使用资源的复数形式不要使用动词
例:查询所有图书

正确示范:https://api.baidu.com/books/

错误示范:https://api.baidu.com/books/get_all_books (不符合规范)

例:删除图书

正确示范:https://api.baidu.com/books/user

错误示范:https://api.baidu.com/books/delete-user

但是,https://api.baidu.com/books/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请求:整体修改主键id为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:指定返回记录的开始位置
  • 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的响应状态码,这里是自定义的响应状态码

  • http请求的状态码(2,3,4,5)
  • 返回的数据,携带状态码(标志当次请求成功或失败)
data = {'code': 200}

8.错误处理,应返回错误信息

返回的数据中,需要携带错误信息

data = {'code': 401, 'error_msg': '客户端出错了'}

9.返回结果,应符合以下规范

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

  • GET /collection:返回资源对象的列表(数组)[{},{},{}]
  • GET /collection/resource:返回单个资源对象 {} 这是字典
  • POST /collection:返回新生成的资源对象 {新增的书}
  • PUT /collection/resource:返回完整的资源对象 {返回修改后的}
  • PATCH /collection/resource:返回完整的资源对象 {返回修改后的};局部修改
  • DELETE /collection/resource:返回一个空文档

单条数据:{}

多条数据:[]

新增数据:返回新增的数据

修改数据:返回修改的数据

删除数据:返回空文档

以上是规范,实际企业是这么做的: {status:100,msg:查询成功,data:null}

10.需要url请求的资源 需要访问资源的请求链接

返回的数据中,携带链接地址

例:查询id为7的用户的信息
{
    "code": 200,
    "msg": "ok",
    "results":[
        {
            "id": 7,
            "name": "baobao",
            "register_data": "2017-06-10 17:36:41",
            "avatar": "https://image.baidu.com/Darker/07.jpg",
            "url": "http://www.baobao.top"
        }
        ...
    ]
}

接口测试工具:Postman

1 后端写好接口要测试,后端开发要使用一个工具测试接口(postman)
2 下载---一路下一步--装成功了
3 会发送http请求,get,post请求即可
4 请求地址带参数,请求体带数据,请求头加数据
5 响应cookie,响应头,响应体

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

Postman可以直接从官网:https://www.getpostman.com/downloads/下载获得,然后进行傻瓜式安装。

  • 工作面板
  • 简易的get请求

drm和fb架构 drf框架入门_django

  • 简易的post请求

drm和fb架构 drf框架入门_django_02

  • 案例:请求百度地图接口

drm和fb架构 drf框架入门_mysql_03

三:DRF快速使用

使用DRF快速写 增删改查 的接口 开始咯;

源码中(csrf已经禁用掉了)

# 首先要在Django项目环境基础上操作,没有就创建Django项目;
# 3.1、安装DRF
 - 前提是已经安装了django,建议安装在虚拟环境
# mkvirtualenv drfdemo -p python3
# pip install django

pip install djangorestframework
pip install pymysql

##3.1.1、创建django项目
cd ~/Desktop
django-admin startproject drfdemo

使用pycharm打开项目,设置虚拟环境的解析器,并修改manage.py中的后缀参数。

# 3.2、注册app
INSTALLED_APPS = [
	
    'rest_framework'
]

# 3.3、创建模型操作类
class Student(models.Model):
    # 模型字段
    name = models.CharField(max_length=100,verbose_name="姓名")
    sex = models.BooleanField(default=1,verbose_name="性别")

# 3.4、 为了方便测试,所以我们可以先创建一个数据库。
create database students charset=utf8;

#3.5、 数据库迁移
# 如果想用mysqal还需要配置DATABASES={} 和 指定设置默认的MySQLDB。
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '数据库名',
        'USER': '用户',
        'PASSWORD': '密码',
        'HOST': 'IP地址',
        'PORT': '端口',
    }
}

# 并且指定设置默认的MySQLDB,需要在项目文件夹或者应用文件夹内的__init__.py文件中书写固定的代码。
import pymysql
pymysql.install_as_MySQLdb()

# 3.6 路由
path('test/', views.Test.as_view()),

# 3.7 视图类views.py 定义视图的行为。
from rest_framework.views import APIView
from rest_framework.response import Response

class Test(APIView):
    def get(self,request):
        return Response({'name':'bao','age':'19'})
    def post(self,request):
        return Response({'name': 'you', 'age': '19'})
    
# 3.8 serializer.py序列化器
from rest_framework.serializers import ModelSerializer
from app import models
class BookSerializer(ModelSerializer):  # 序列化器是用来定义API的表示形式。
    class Meta:
        model = models.Book
        fields = '__all__'

# 在请求地址中访问
http://127.0.0.1:8001/test/

特点:

# 具体功能在具体模块下
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from rest_framework.filters import OrderingFilter
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.settings import APISettings

# 自定义drf配置 - 在自己的settings.py

REST_FRAMEWORK = {
    # 自定义修改drf的配置们
}

详细点的:

3.1 安装DRF

前提是已经安装了django,建议安装在虚拟环境

# mkvirtualenv drfdemo -p python3
# pip install django

pip install djangorestframework
pip install pymysql

3.1.1 创建django项目

cd ~/Desktop
django-admin startproject drfdemo

使用pycharm打开项目,设置虚拟环境的解析器,并修改manage.py中的后缀参数。(就是设置虚拟环境而已)

3.2 在setting的app中配置注册rest-framework

注册顺序没强制要求;在settings.pyINSTALLED_APPS中添加’rest_framework’。

INSTALLED_APPS = [
    'rest_framework'
]

接下来就可以使用DRF提供的功能进行api接口开发了。在项目中如果使用rest_framework框架实现API接口,主要有以下三个步骤:

  • 将请求的数据(如JSON格式)转换为模型类对象
  • 操作数据库
  • 将模型类对象转换为响应的数据(如JSON格式)

接下来,我们快速体验下我们搞懂drf以后的开发代码。接下来代码不需要理解,看步骤。

体验drf完全简写代码的过程(了解)

使用DRF快速写 增删改查 的接口; 开始咯;

为了方便测试,所以我们可以先创建一个数据库。

create database drf charset=utf8;

可能你还需要 初始化数据库连接

安装pymysql
pip install pymysql

主引用中__init__.py设置使用pymysql作为数据库驱动

# 并且指定设置默认的MySQLDB,需要在项目文件夹或者应用文件夹内的__init__.py文件中书写固定的代码。
import pymysql
pymysql.install_as_MySQLdb()

settings.py配置文件中设置mysql的账号密码

# 如果想用mysqal还需要配置DATABASES={} 和 指定设置默认的MySQLDB。
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '数据库名',
        'USER': '用户',
        'PASSWORD': '密码',
        'HOST': 'IP地址',
        'PORT': '端口',
    }
}

3.3 创建模型操作类models.py

from django.db import models

# Create your models here.


class Book(models.Model):
    name = models.CharField(max_length=18)
    publish = models.CharField(max_length=32)
    price = models.IntegerField()

3.4 执行数据迁移

python manage.py makemigrations
python manage.py migrate

如果中途报错 :

# 执行数据迁移 python manage.py makemigrations 报错如下:

drm和fb架构 drf框架入门_mysql_04

解决方案:

注释掉 backends/mysql/base.py中的35和36行代码。

drm和fb架构 drf框架入门_mysql_05

# 执行数据迁移发生以下错误:

drm和fb架构 drf框架入门_mysql_06

解决方法:

backends/mysql/operations.py146行里面新增一个行代码:

drm和fb架构 drf框架入门_数据_07

好了回到正题!

记得在数据库中增加点书本数据哦!

3.5 编写视图views.py

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

3.6 新建序列化器。

在app应用目录中新建serializers.py用于保存该应用的序列化器。

创建一个StudentModelSerializer用于序列化与反序列化。

serializer.py

# 创建序列化器类,回头会在试图中被调用
from rest_framework.serializers import ModelSerializer
from app import models
class BookSerializer(ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
  • model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
  • fields 指明该序列化器包含模型类中的哪些字段,’all‘指明包含所有字段

3.7 urls.py

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

接下来用浏览器或者postman工具测试,看! 发送GET请求就能查询到数据了,也可以指定id单独查某条数据。

drm和fb架构 drf框架入门_数据_08

POST增加数据:

drm和fb架构 drf框架入门_mysql_09

这是再GET查询全部显示出来的书里就有新增的那本书了。

drm和fb架构 drf框架入门_django_10

PACH修改数据:要指定数据的id

drm和fb架构 drf框架入门_django_11

DELETE删除数据:删除单条数据要指定id 删除哈!、

drm和fb架构 drf框架入门_drm和fb架构_12

再查询就没有了id为3的数据(南京纪念馆)

四:CBV和APIView源码分析

Django CBV 和drf CBV对比

Django CBV

  1. 继承了View视图类
  2. 通过as_view()来获取view函数地址
  3. 请求来了之后,调用view函数,内部调用dispatch函数完成请求的分发
  4. dispatch函数将请求方式映射成视图类的同名方法,完成请求的处理,得到相应、
  5. 最后将相应的结果一层层返回

drf CBV

  1. 继承了APIView
  2. 通过as_view()(继承自django的as_view)获取view函数地址,但在view函数中局部禁用了csrf认证
  3. 请求来了调用view函数,内部调用(APIView类的)dispatch函数完成请求分发
  4. dispatch函数 二次封装request进行三大认证后,再将请求方式映射成视图类的同名方法,完成请求的处理,得到相应,再对相应做渲染处理
  5. 最后将相应的结果一层层返回

4.1 APIView的as_view

  • 内部还是执行了原生Django的View内部的闭包函数view
  • 禁用了csrf
  • 一切皆对象,函数也是对象:函数地址.name='Darker'

APIView的执行流程

# path('test/',APIView类的as_view内部是用了View的as_view内的view闭包函数),
    '''
    1 path的第二个参数是:APIView类的as_view内部是用了View的as_view内的view闭包函数
    2 一旦有请求来了,匹配test路径成功
    3 执行第二个参数view函数内存地址(requset),还是执行View的as_view内的view闭包函数,但是加了个csrf_exempt装饰器
    4 所以,继承了APIView的所有接口,都没有csrf的校验了 (*****************)
    5 执行self.dispatch(request)----》APIView类的
        def dispatch(self, request, *args, **kwargs):
            # 以后所有的request对象,都是****新的request对象***,它是drf的Request类的对象
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            try:
                #整个drf的执行流程内的权限,频率,认证
                self.initial(request, *args, **kwargs)
                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

    '''
    
### request = self.initialize_request(request, *args, **kwargs)
##返回的request对象是drf   Request类的request对象
def initialize_request(self, request, *args, **kwargs):
    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )
### *******以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了



 #####你需要记住的
	-0 所有的csrf都不校验了
	-1 request对象变成了新的request对象,drf的request对象
    -2 执行了权限,频率,认证
    -3 捕获了全局异常(统一处理异常)
    -4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
    -5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了

补充

1 装饰器函数: csrf_exempt
#示例:
@csrf_exempt
def test():
    pass

#本质就是,这种写法也是加装饰器的效果,但是很古怪,不过用在ur中到有点意思
test=csrf_exempt(test)

#看看urls.py中的
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', 装饰器auth(views.index)),  # 加了个auth认证装饰器,那么再views中就不需要@auth..这种写法啦!有点装X
]

4.2 cbv执行流程/原生View的as_view

  • 本质上,执行了self.dispatch(request, *args, **lwargs),执行的是APIViewpatch
path('test/',views.TestView.as_view()),
# path('test/',View类的as_view内部有个view闭包函数内存地址),
'''
    1 path的第二个参数是:View类的as_view内部有个view闭包函数内存地址
    2 一旦有请求来了,匹配test路径成功
    3 执行第二个参数view函数内存地址(requset)
    4 本质执行了self.dispatch(request)
    5 通过反射去获得方法(如果是get请求,就是get方法)
     if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    6 执行get方法,传入参数
    handler(request, *args, **kwargs)
    '''

3.dispatch源码分析

def dispatch(self, request, *args, **kwargs):
    self.args = args
    self.kwargs = kwargs
    # DRF的Reauest对象,内部有request._request,是原生的request
    request = self.initialize_request(request, *args, **kwargs)
    # 现在的request是新的request,是drf的Request对象
    self.request = request

    try:
        self.initial(request, *args, **kwargs)

        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的CBV源码分析详解

1.一开始进入根路径,根据路由找视图,执行了as_view()

drm和fb架构 drf框架入门_drm和fb架构_13


相当于

path('', views.Index.as_view()(request))

2.但是Index这个类里面并没有as_view(),所以调用了Index父类APIViewas_view()

这里的APIView来自rest_frameworkviews

drm和fb架构 drf框架入门_drm和fb架构_14


3.找到as_view()

drm和fb架构 drf框架入门_django_15

4.调用了父类的as_view()

并且,禁用了csrf:这个效果和 加装饰器局部禁用csrf 是一样的

drm和fb架构 drf框架入门_drm和fb架构_16


5.这个父类的as_view()就是原生Django的View下的as_view()

所以,真正的程序在执行的时候,还是执行的原生Django的view

一切皆对象,函数也是对象:所以也可以通过.的方法来取值和赋值

drm和fb架构 drf框架入门_django_17


6.在原生Django的as_view中,最后返回的是self.dispatch

这里的self是视图里面定义的类,也就是Index

Index继承的是APIView,在APIView中,有自己的dispatch方法

drm和fb架构 drf框架入门_drm和fb架构_18


7.这里request = self.initialize_request(request, *args, **kwargs)self依旧是Index

但是在Index中,并没有initialize_request方法,所以就去父类APIView中找

drm和fb架构 drf框架入门_django_19


8.在APIView中,确实存在initialize_request

drm和fb架构 drf框架入门_drm和fb架构_20


9.将原始的request传进来,最后实例化,并返回了1个Request对象(DRF的Request

drm和fb架构 drf框架入门_django_21


这里的返回的Request对象,就是from rest_framework.response import ResponseRequest对象

四:Request类源码分析

1.Request类中

  • request._request:原生request
  • request.data:POST请求提交的数据(urlencoded、json、formdata)
  • request.user:不是原生的user了
  • request.query_params:原生的request.GET,遵循RESTful规范(6.查询参数,也就是GET请求获取的?后的参数
  • 重写了__getattr__、新的request.原来的所有属性和方法:都可以直接用.拿到
1 django 原生的Request:django.core.handlers.wsgi.WSGIRequest
2 drf的Request:rest_framework.request.Request

3 drf的request对象内有原生的request
	request._request:原生的Request
4 在视图类中使用
	request.method  拿到的就是请求方式,
    正常拿,应该request._request.method
5 如何实现这种操作?
	-对象.属性会触发 类的__getattr__方法
    
    
6 drf的Request类重写了__getattr__
    def __getattr__(self, attr):
        try:
            # 去原生的request反射属性
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
        
        
 7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
	-request.data  #post请求提交的数据,不论什么格式,都在它中
    -requst.query_params# get请求提交的数据(查询参数)
    
    
8 重点记住:
	-drf的request对象用起来跟原来一样(重写了__getattr__)
    -request.data  #post请求提交的数据,不论什么格式,都在它中
    -requst.query_params# get请求提交的数据(查询参数)

详解

1.在APIView源码中,最后返回的是Request对象

路径:rest_framework - request.py - Request

drm和fb架构 drf框架入门_django_22


2.上面的request是原生的,然后被传到了self._request中,被当做内部变量

也就是说,之后的操作中:request._request才是原来的request

drm和fb架构 drf框架入门_django_23


3.上面的request还是原生的,下面的request是新的,是DRF的Request类的对象

这个新的request里面包含了原生request是:request._request(此处用到了面向对象的封装 )

drm和fb架构 drf框架入门_django_24


4.此处的:self.initial(request, *args, **kwargs) 完成了权限频率认证

这里的request已经是新的request

drm和fb架构 drf框架入门_django_25


5.这里的inital里面,就包括了:权限、频率、认证

drm和fb架构 drf框架入门_django_26


)

self.perform_authentication(request)    # 认证相关
self.check_permissions(request)            # 权限相关
self.check_throttles(request)            # 频率相关

6.这里的方法和之前原生django的dispatch一样

发送什么请求,就会执行request.method的请求方式的方法

drm和fb架构 drf框架入门_mysql_27


7.所以,在这个位置的request就是新的request

drm和fb架构 drf框架入门_django_28


8.此处可以打印request(新的)和request._request(原生的)的类型

drm和fb架构 drf框架入门_数据_29


DRF的request:rest_framework.request.Request

原生的request:django.core.handlers.wsgi.WSGIRequest

9.也可以打印request(新的)和request._request(原生的)的method方法,看看发送的是什么请求

drm和fb架构 drf框架入门_django_30


10.原生的request新的request都有method方法,说明它的内部肯定重写了__getattr__方法

from rest_framework.request import Request

它在内部直接通过反射,去_request(也就是原生request)获取了需要的attr

也就是说,原来的request对象的用法,这个新的request都可以用

drm和fb架构 drf框架入门_mysql_31


11.全局的异常捕获

这里会捕获一个全局的异常(例如:没有权限,超出访问评率,操作有误)

相当于在中间件的Exception

drm和fb架构 drf框架入门_django_32


12.把视图函数(视图类)的response进行了二次封装

drm和fb架构 drf框架入门_django_33


1.内容有错还请在评论区指出哦!谢谢!