Django drf请求模块源码解析


Posted in Python onJune 08, 2021

DRF 框架,全称为 Django Rest Framework,是 Django 内置模块的扩展,用于创建标准化 RESTful API;它利用 ORM 映射数据库,并自定义序列化数据进行返回,多用于前后端分离项目

项目地址:

https://github.com/encode/django-rest-framework

请求模块:request对象

源码入口

APIView类中dispatch方法中的:request=self.iniialize_request(*args, **kwargs),源码如下:

def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object.
    """
    parser_context = self.get_parser_context(request)

    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )

源码分析

源码很简单,第1句parser_context = self.get_parser_context(request),我们进入方法get_parser_context查看源码:

"""
Returns a dict that is passed through to Parser.parse(),
as the `parser_context` keyword argument.
"""
# Note: Additionally `request` and `encoding` will also be added
#       to the context by the Request object.
return {
    'view': self,
    'args': getattr(self, 'args', ()),
    'kwargs': getattr(self, 'kwargs', {})
}

上面的代码的意思是:返回一个解析的字典以便于Parser.parse()去解析,另外还通过Request对象添加了上下文requestencoding

第二句返回了一个Request对象,点击进入查看

Django drf请求模块源码解析

我们可以分析出,内部对request做了二次封装,_request是一个HttpRequest对象,并且Request类中还有__getattr__此方法,代码如下:

def __getattr__(self, attr):
    """
    If an attribute does not exist on this instance, then we also attempt
    to proxy it to the underlying HttpRequest object.
    """
    try:
        return getattr(self._request, attr)
    except AttributeError:
        return self.__getattribute__(attr)

意思是如果这个实例上不存在一个属性,那么我们也会尝试将其代理到底层HttpRequest对象。接下来我们可以通过案例演示

案例演示

Django drf请求模块源码解析

我们创建了TestView视图,视图函数中打印了3个request属性,并且在response上打了一个断点,接下来通过url访问视图,进入断点如下,

Django drf请求模块源码解析

我们可以清楚的看到:

  • request是drfRequest对象
  • request下有data属性,query_params属性,但是没有GET属性

上面还有一个Protected Attributes属性,里面包含了_request属性

Django drf请求模块源码解析

我们可以看到_requestWSGIHttpRequest对象,所以它会有GET属性,所以我们视图中打印的request.GET实际上和request._request.GET是一样的,因为request没有GET属性,所以它就会访问_request中的GET属性,最后我们查看打印结果,如下:

<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>

同样的,POST请求也是如此,我们在视图中添加POST的请求方式,如下:

def post(self, request, *args, **kwargs):
    print(request.POST)  # 兼容
    print(request._request.POST)  # 二次封装
    print(request.data)  # 拓展,兼容性最强,3种请求方式都可以
    return Response("drf post ok")

我们都知道提交数据一般有3种方式

  • multipart/form-data
  • application/x-www-form-urlencoded
  • application/json

首先我们使用multipart/form-data提交请求数据,并请求API

Django drf请求模块源码解析

我们查看pycharm打印结果

<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>

可以看到multipart/form-data这种请求方式,都能打印出来

接着我们使用application/x-www-form-urlencoded提交请求数据,并请求API

Django drf请求模块源码解析

<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>
<QueryDict: {'a': ['1']}>

可以看到application/x-www-form-urlencoded这种请求方式,都能打印出来

最后我们使用application/json提交请求数据,并请求API

Django drf请求模块源码解析

可以看到application/json这种请求方式,只有request.data能打印出来

<QueryDict: {}>
<QueryDict: {}>
{'a': 1}

所以request.data兼容性最强

总结drfrequest进行了二次封装,request._request就是原生的WSGIRequest原生request的属性和方法都可以被drfrequest对象直接访问(兼容)drf请求的所有url拼接参数均被解析到query_params中,所有的数据包均被解析到data中其中post请求,request.data的兼容性最强,能兼容前台传输的json格式的数据

到此这篇关于Django(48)drf请求模块源码分析 的文章就介绍到这了,更多相关Django drf源码内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python深入学习之内存管理
Aug 31 Python
Python去除列表中重复元素的方法
Mar 20 Python
举例讲解Python面相对象编程中对象的属性与类的方法
Jan 19 Python
正确理解python中的关键字“with”与上下文管理器
Apr 21 Python
python图书管理系统
Apr 05 Python
对Python中DataFrame按照行遍历的方法
Apr 08 Python
详解python深浅拷贝区别
Jun 24 Python
python3使用腾讯企业邮箱发送邮件的实例
Jun 28 Python
淘宝秒杀python脚本 扫码登录版
Sep 19 Python
解决python 读取excel时 日期变成数字并加.0的问题
Oct 08 Python
Django中密码的加密、验密、解密操作
Dec 19 Python
python ftplib模块使用代码实例
Dec 31 Python
Python中OpenCV实现查找轮廓的实例
python字符串的多行输出的实例详解
Jun 08 #Python
Python机器学习之基于Pytorch实现猫狗分类
Python中json.load()和json.loads()有哪些区别
python 爬取哔哩哔哩up主信息和投稿视频
Jun 07 #Python
OpenCV-Python直方图均衡化实现图像去雾
OpenCV-Python实现人脸磨皮算法
You might like
PHP 的 __FILE__ 常量
2007/01/15 PHP
php获取$_POST同名参数数组的实现介绍
2013/06/30 PHP
php按百分比生成缩略图的代码分享
2014/05/10 PHP
Thinkphp中的volist标签用法简介
2014/06/18 PHP
php mysql操作mysql_connect连接数据库实例详解
2016/12/26 PHP
PHP切割汉字的常用方法实例总结
2019/04/27 PHP
jquery.alert 弹出式复选框实现代码
2009/06/15 Javascript
node.js 一个简单的页面输出实现代码
2012/03/07 Javascript
form表单只提交数据而不进行页面跳转的解决方案
2013/09/18 Javascript
jquery text(),val(),html()方法区别总结
2013/11/04 Javascript
document.execCommand()的用法小结
2014/01/08 Javascript
使用javascript为网页增加夜间模式
2014/01/26 Javascript
javascript操作数组详解
2014/12/17 Javascript
js实现滚动条滚动到某个位置便自动定位某个tr
2021/01/20 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
前端框架Vue.js中Directive知识详解
2016/09/12 Javascript
vue 通过下拉框组件学习vue中的父子通讯
2017/12/19 Javascript
Angular6中使用Swiper的方法示例
2018/07/09 Javascript
JavaScrip数组去重操作实例小结
2019/06/20 Javascript
基于Electron实现桌面应用开发代码实例
2020/07/07 Javascript
javaScript代码飘红报错看不懂?读完这篇文章再试试
2020/08/19 Javascript
js基于canvas实现时钟组件
2021/02/07 Javascript
python爬虫之模拟登陆csdn的实例代码
2018/05/18 Python
原生python实现knn分类算法
2019/10/24 Python
Python2和Python3中@abstractmethod使用方法
2020/02/04 Python
Python中zip()函数的解释和可视化(实例详解)
2020/02/16 Python
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
PHP如何防止SQL注入
2014/05/03 面试题
PHP两种查询函数array/row的区别
2013/06/03 面试题
公益活动策划方案
2014/01/09 职场文书
个人评价范文分享
2014/01/11 职场文书
初中美术教学反思
2014/01/29 职场文书
公司法人授权委托书范本
2014/09/12 职场文书
财务务虚会发言材料
2014/10/20 职场文书
个人房屋转让协议书范本
2014/10/26 职场文书
导游词之太行山青龙峡
2020/01/14 职场文书