DRF从入门到精通二(Request源码分析、DRF之序列化组件)

文章目录

  • 一、Request对象源码分析
    • 区分原生request和新生request
    • 新的request还能像原来的reqeust一样使用吗
    • 源码片段分析
    • 总结:
  • 二、DRF之序列化组件
    • 序列化介绍
    • 序列化步骤
    • 序列化组件的基本使用
    • 反序列化基本使用
      • 反序列化的新增
      • 反序列化的新增
      • 删除单条
    • 反序列化的校验

一、Request对象源码分析

在上一篇博客中最后分析APIView时,我们分析出继承了APIView的视图,以后request都是新的request了,是DRF提供的Request的对象

区分原生request和新生request

	原生request:django.core.handlers.wsgi.WSGIRequest新生request:from rest_framework.request import Request原生request可以在新生request._request中获取

新的request还能像原来的reqeust一样使用吗

	用起来屎一样的,新的request只是在原来的request基础上添加了一些功能,并不影响基础功能的使用,其本质就是类似装饰器print(request.method)  # getprint(request.path)  # /movies/print(request.GET)   # 原来的get请求提交的参数print(request.POST)  # 原来post请求提交的参数

源码片段分析

	'''源码解析之 __init__'''从上面区分原生request和新的request中可以知道,老的request对象其实就是在新的内部,request._request中'我们先看__init__,它是一个初始化方法,类实例化得到对象时,会执行它,然后会往对象中放数据'def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):'''传入的request是老的,django原生的request放到self._request,self是新的request类的对象这里它把传入过来的原request放到这个self._request中,这里的self已经不是视图类了,因为这个Request类没有继承任何一个类,它就是它自己,所以这个self是Request'''self._request = requestself._data = Emptyself._files = Empty.....

在类内部,以 __开头 __结尾的方法, 在某种情况下会自动调用,他们称之为魔法方法。具体有那些,可以自行搜索,因为所有的类都继承了Object类,所以也可以在Object类中看看,但是不全里面

在这里插入图片描述

	'''源码解析之__getattr__'''类中有个魔法方法:__getattr__,对象.属性,属性不存在会触发它的执行def __getattr__(self, attr): 如果取的属性不存在会去原生的Django的request对象中取出来try:'通过反射,因为这里是self._request所以去Django的request取,能取到就返回,娶不到就执行except代码,如果还取不到则报错'return getattr(self._request, attr)except AttributeError:return self.__getattribute__(attr)'以后用的所有属性或方法,直接用就可以了(通过反射去原来的request中取)' 

以后新的request中多了一个属性data,它会把前端post/put提交的请求体中的数据,都放在request.data中,无论何种编码格式,它都是字典

	data是一个方法,被property装饰了,变成了数据属性用-以后body中提交的数据,都从这里取(request.POST)-urlencoded,form-data:提交的数据在request.POST中-json格式提交的数据,在request.POST中是没有的,它在request.body中-现在无论那种格式,都可以直接从request.data中取request.query_params:get请求提交的参数,以后从这里取request.FILES:取文件就还是从这个里面取,和之前一样

总结:

	1.新的request跟之前的用法一模一样,如果新的request取不到,它使用__getattr__魔法方法去原生request中取。当然原生的也可以直接在新的request中拿到,request._request2.新的request中多了data属性,request.data客户端提交的请求体中的数据,无论是什么编码都在request.data中3.其他的使用和原生的request一模一样request.query_params就是原来的request._request.GET上传的文件从request.FILES'''1.原生Django提交数据(post),只能处理urlencoded和form-data编码,从request.POST中取2.原生Django提交数据(put),处理不了,需要我们从request.body中取出来进行处理分不同编码格式:urlencoded------》例:name=lqz&age=19---》使用字符串切割的方式.splitjson----->{'xxx':'xx','yyy':'yy'}--->需要自己进行json.loads反序列化3.原生Django不能处理json提交的数据(post/put),需要自己做反序列化json----->{'xxx':'xx','yyy':'yy'}--->需要自己进行json.loads反序列化4.新的request解决了所有问题:request.data'''

二、DRF之序列化组件

	序列化类(组件)可以做的事情:1.序列化,QuerySet对象,单个对象做序列化给前端2.反序列化数据校验:前端传入数据后校验数据是否合法3.反序列化数据保存:前端传入数据,存到数据库中

序列化介绍

  • 在写接口时,需要序列化和反序列化,而且反序列化的过程中要做数据校验,drf直接提供了固定的写法,只需要按照固定写法,只需要按照固定写法使用,就能完成上面的三个需求。
  • 提供了两个类SerializerModelSerializer,编写自定义的类,只需要继承drf提供的序列化类,就可以使用其中的某些方法,也能完成上面的三个需求

序列化类的作用:做序列化、反序列化、反序列化校验

序列化步骤

	1.写一个py文件,叫serializer.py(命名随意)2.写一个序列化类,继承serializers.Serializer,3.在类中编写需要序列化的字段例:name=serializers.CharField()4.在视图类中使用,导入models文件中的类books,然后实例化得到对象,对查出来的query对象们,对单个对象序列化并传入instance=books参数如果query是复数,一定要串many=True,如果query是单个对象,就无需传入many5.序列化类对象:ser.data---->字典或列表----->通过Response将json格式字符串返回给前端

序列化组件的基本使用

1.创建一个py文件 ----》serializer.pyfrom rest_framework import serializersclass BookSerializer(serializers.ModelSerializer):name = serializers.CharField(max_length=18, min_length=2, required=True)price = serializers.IntegerField(required=True)class Meta:model = Bookfields = '__all__'2.view.py文件中from app01 import modelsfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .serializer import BookSerializerclass BookView(APIView):def get(self, request):book_list = models.Book.objects.all()ser = BookSerializer(instance=book_list, many=True)  # 序列化多条需要many=Truereturn Response({'code': 100, 'msg': '查询成功', 'results': ser.data}) # 无论是列表还是字典都可以序列化class BookDetailView(APIView):def get(self, request, pk):book_obj = models.Book.objects.filter(pk=pk).first()ser = BookSerializer(instance=book_obj)if ser.is_valid():return Response({'code': 100, 'msg': '查询一条成功', 'results': ser})else:return Response(ser.errors)3.urls.py文件中urlpatterns = [path('books/', views.BookView.as_view()),path('books/<int:pk>', views.BookDetailView.as_view()),]

在这里插入图片描述

反序列化基本使用

反序列化过程:新增、修改

	新增:1. 前端传入后端的数据,不论编码格式,都在request.data中,request.data格式是字典前端根据传入的编码格式不一样,从request.data取到的字典形式也是不一样的编码格式                   字典urlencoded               QueryDictform-data                QueryDictjson                       dict2. 将前端传入的数据request.data进行反序列化,并完成序列化类的反序列化3. 序列化类得到对象并传入参数:data=request.data校验数据保存:ser.save()--->序列化类中重写create方法修改:1. 拿到前端传入的数据,进行反序列化,查出要修改的对象--->序列化类的反序列化2. 序列化类得到对象,传入参数:instance=要修改的对象,data=request.data校验数据 保存:ser.save()  --->序列化类中重写update方法

反序列化的新增

序列化类

	class BookSerializer(serializers.ModelSerializer):name = serializers.CharField()price = serializers.IntegerField()class Meta:model = Bookfields = '__all__'# 新增一条数据def create(self, validated_data):# 保存的逻辑# validated_data 校验过后的数据 {name,price,publish}# 保存到数据库book = Book.objects.create(**validated_data)# 一定不要忘记返回新增的对象return book

视图类

	class BookView(APIView):def get(self, request):  # 获取多条数据book_list = models.Book.objects.all()'''instance表示要序列化的数据,many=True表示序列化多条(instance是QuerySet对象)'''ser = BookSerializer(instance=book_list, many=True)  # 序列化多条需要many=Truereturn Response({'code': 100, 'msg': '查询成功', 'results': ser.data})def post(self, request):ser = BookSerializer(data=request.data)  # 从前端传递数据从request.data中取出来if ser.is_valid():  # is_valid表示校验前端传入的数据,但是我们没有写校验规则# 保存,需要自己写,要在序列化类BookSerializer中重写create方法ser.save()  # 调用ser.save,自动触发自定义编辑create方法保存数据'''这个时候发送post请求会发生报错,NotImplementedError: `create()` must be implemented.这个时候点击我们点击save查看源码是调用了Save会触发BaseSerializer的方法判断了 如果instance有值执行update,没有值执行create 看到create没有写 所以我们得重写Create'''return Response({'code': 100, 'msg': '添加成功', 'results': ser.data})else:return Response({'code': 101, 'msg': ser.errors})

反序列化的新增

序列化类

	class BookSerializer(serializers.ModelSerializer):name = serializers.CharField()price = serializers.IntegerField()class Meta:model = Bookfields = '__all__'# 修改对象def update(self, instance, validated_data):# instance 要修改的对象# validated_date 校验过后的数据instance.name = validated_data.get('name')instance.price = validated_data.get('price')instance.save()  # orm的单个对象,修改了单个对象的属性,只要调用对象.save就可以修改保存到数据库return instance  # 记得把修改的对象返回

视图类

	class BookDetailView(APIView):def get(self, request, pk):  # 获取单条数据book_obj = models.Book.objects.filter(pk=pk).first()ser = BookSerializer(instance=book_obj)return Response({'code': 100, 'msg': '查询一条成功', 'results': ser.data})def put(self, request, pk):book_obj = models.Book.objects.filter(pk=pk).first()ser = BookSerializer(instance=book_obj,data=request.data)if ser.is_valid():ser.save()  # 同新增一样,需要重写update方法return Response({'code': 100, 'msg': '修改一条成功', 'results': ser.data})else:return Response({'code': 101, 'msg': ser.errors})

删除单条

	class BookDetailView(APIView):def delete(self,request,pk):models.Book.objects.filter(pk=pk).delete()return Response({'code': 100, 'msg': '删除一条成功'})

反序列化的校验

反序列化的数据校验功能类比forms组件

  • 局部钩子
  • 全局钩子

代码实现

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Bookclass BookSerializer(serializers.ModelSerializer):name = serializers.CharField(max_length=18, min_length=2, required=True)price = serializers.IntegerField(required=True)publish = serializers.CharField(min_length=3)class Meta:model = Bookfields = '__all__'# 新增一条数据def create(self, validated_data):# 保存的逻辑# validated_data 校验过后的数据 {name,price,publish}# 保存到数据库book = Book.objects.create(**validated_data)# 一定不要忘记返回新增的对象return book# 修改对象def update(self, instance, validated_data):# instance 要修改的对象# validated_date 校验过后的数据instance.name = validated_data.get('name')instance.price = validated_data.get('price')instance.save()  # orm的单个对象,修改了单个对象的属性,只要调用对象.save就可以修改保存到数据库return instance  # 记得把修改的对象返回# 局部钩子def validate_price(self,price):if price < 10 or price > 999:raise ValidationError('价格不能高于999或者低于10')return price# 全局钩子def validate(self, attrs):# 校验过后的数据,出版社后三位文字与书名后三位不能一样if attrs.get('publish')[-3] == attrs.get('name')[-3]:raise ValidationError('出版社后三位文字不能与书名后三位一样!')return attrs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/234727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mangokit:golang web项目管理工具,使用proto定义http路由和错误

文章目录 前言1、mangokit介绍1.1 根据proto文件生成http路由1.2 根据proto文件生成响应码1.3 使用wire来管理依赖注入 2、mangokit实现2.1 protobuf插件开发2.2 mangokit工具 3、使用示例3.1 创建新项目3.2 添加新的proto文件3.3 代码生成 前言 在使用gin框架开发web应用时&a…

Linux学习(1)——初识Linux

目录 一、Linux的哲学思想 1.1 基础知识 1.2 根目录下的文件夹 二、Shell 1、Shell的定义 2、Shell的作用 三、Linux命令行 1、Linux通用命令行使用格式 四、Linux命令的分类 1、内部命令和外部命令的理解 2、内部命令和外部命令的区别 3、命令的执行过程 五、编辑…

[每周一更]-(第31期):Mysql安装汇总

写自&#xff1a;20230204 23:25 一. mysql rpm二进制包 rpm -Uvh http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm yum install mysql-community-server service mysqld start set password password(“123456”)二. mysql yum安装 1、安装查看有没有安装…

开源高星精选,10个2023企业级Python测试项目,再不学习今年没了

纸上得来终觉浅&#xff0c;光学习理论知识是不够的。 想要学好软件测试必须要结合实战项目深入掌握&#xff0c;今天给大家分享十个2023最新企业级Python软件测试项目&#xff1a; ▌Rank 1&#xff1a;Requests-HTML v0.9&#xff08;7385 stars on Github&#xff0c;来自K…

Python-基于fastapi实现SSE流式返回(类似GPT)

最近在做大模型对话相关功能&#xff0c;需要将对话内容流式返回给前端页面&#xff08;类似GPT的效果&#xff09;。下面直接说下如何实现&#xff1a; 1.首先导入fastapi和sse流式返回所需要的包 from fastapi import APIRouter, Response, status from sse_starlette.sse …

以太网的数据速率、互连介质和物理层规范

以太网协议连接已经广泛应用于我们周围的大量事物或设备中。过去&#xff0c;以太网用在局域网 (LAN) 和城域网 (MAN) 中&#xff0c;而如今&#xff0c;由于以太网的普及和多种优势&#xff0c;例如巨大的生态体系和日益增长的规模经济&#xff0c;它越来越多地用在存储和汽车…

鉴赏 tcp vegas

优秀的 vegas 之后&#xff0c;再鉴赏一下迄今唯一像那么回事的拥塞控制算法 vegas。 从下图可看出所有的(对&#xff0c;所有的) aimd 都毫无伸缩性(z:吞吐&#xff0c;x:rtt&#xff0c;y:丢包率&#xff0c;由 buffer_size 直接决定)&#xff1a; 一下就可看出 rtt 和 bu…

(四)pytorch图像识别实战之用resnet18实现花朵分类(代码+详细注解)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、关于这个实战的一些知识点Q1&#xff1a;图像识别实战常用模块解读Q2:数据增强Q3:迁移学习Q4&#xff1a;平均全局池化Q5&#xff1a;设置哪些层需要训练时…

大一C语言查缺补漏1 12.2

学习方向非C语言方向&#xff0c;但是专业是。。 仅供参考&#xff0c;&#xff0c;祝大家期末考试顺利。 对于二维数组定义&#xff0c;要给出明确的定义 eg&#xff1a;double a [21][4] int a [ ][3] {1,2,3,4,5,6} 不可以是&#xff1a;int a [ ][3]&#xff1b; 在c…

Unity3d C#利用Editor编辑器拓展实现配置UI背景样式一键设置UI背景样式功能(含源码)

前言 在开发UI滚动列表的时候&#xff0c;经常会有每项的背景图不统一的情况&#xff0c;会间隔重复的情况居多。这种情况下&#xff0c;手动去设置间隔一行的背景图或者颜色是比较麻烦的。在此背景下&#xff0c;笔者尝试写个小工具&#xff0c;在搭建UI时配置一下循环背景的…

《数据结构、算法与应用C++语言描述》- 最小赢者树模板的C++实现

赢者树 完整可编译运行代码见&#xff1a;Github::Data-Structures-Algorithms-and-Applications/_30winnerTree 比赛规则 假定有 n 个选手参加一次网球比赛。比赛规则是“突然死亡法”(sudden-death mode)&#xff1a;一名选手只要输掉一场球&#xff0c;就被淘汰。一对一对…

fill-in-the-middle(FIM) 实现与简单应用

1 背景 传统训练的 GPT 模型只能根据前文内容预测后文内容&#xff0c;但有些应用比如代码生成器&#xff0c;需要我们给出上文和下文&#xff0c;使模型可以预测中间的内容&#xff0c;传统训练的 GPT 就不能完成这类任务。 传统训练的 GPT 只能根据上文预测下文 使用 FIM…

vue-element安装富文本编辑器vue-quill-editor教程

在vue ui面板中安装vue-quill-editor依赖 命令安装 npm install vue-quill-editor --save # or yarn add vue-quill-editor 使用方法 在main.js导入富文本编辑器 import VueQuillEditor from vue-quill-editor import quill/dist/quill.core.css // import styles import…

技术博客:市面上加密混淆软件的比较和推荐

技术博客&#xff1a;市面上加密混淆软件的比较和推荐 引言 市面上有许多加密混淆软件可供开发者使用&#xff0c;但哪些软件是最好用的&#xff1f;哪些软件受到开发者的喜爱&#xff1f;本文将根据一次在CSDN上的投票结果&#xff0c;为大家介绍几款在程序员中普及度较高的…

CEC2013(python):五种算法(ABC、PSO、CSO、OOA、DBO)求解CEC2013(python代码)

一、五种算法简介 1、人工蜂群算法 &#xff08;Artificial Bee Colony Algorithm, ABC&#xff09; 2、粒子群优化算法PSO 3、鸡群优化算法CSO 4、鱼鹰优化算法OOA 5、蜣螂优化算法DBO 二、5种算法求解CEC2013 &#xff08;1&#xff09;CEC2013简介 参考文献&#xff…

WINDOWS(WIN11)通过IP添加网络打印机

点击添加设备 点击手动添加 使用IP地址或主机名添加打印机 选择TCP/IP设备&#xff0c;输入打印机地址 如果有正确驱动就安装&#xff0c;没有就取消。 通过手动设置添加本地打印机或网络打印机 使用现有的端口 根据打印机IP&#xff0c;选择标准端口。 成功&#xff01; 到…

机器学习笔记:支持向量机回归SVR

1 主要思想 主要思路类似于机器学习笔记&#xff1a;支持向量机SVM_支撑向量学习-CSDN博客 和SVM的区别主要有 解法和SVM区别不大&#xff0c;也是KKT 2 和线性回归的区别 对SVR&#xff0c;如果f(x)和y之间的差距小于阈值ε【也即落在两条间隔带之间】&#xff0c;则不计算…

模拟组建网络的过程

DNS是域名系统&#xff0c;作用是将域名解析成ip地址 要求 1.使用172.16.0.0网段组建网络 2.使用3台pc&#xff0c;可以配置DHCP服务自动分配ip 3.添加两个网站服务器 第一台是www.taobao.com 第二台www.jd.com 他们可以通过DNS服务器为客户解析域名 172开头的是B类ip地…

标准库中的string类(上)——“C++”

各位CSDN的uu们好呀&#xff0c;好久没有更新小雅兰的C专栏的知识啦&#xff0c;接下来一段时间&#xff0c;小雅兰就又会开始更新C这方面的知识点啦&#xff0c;以及期末复习的一些知识点&#xff0c;下面&#xff0c;让我们进入西嘎嘎string的世界吧&#xff01;&#xff01;…

【论文简述】High-frequency Stereo Matching Network(CVPR 2023)

一、论文简述 1. 第一作者&#xff1a;Haoliang Zhao 2. 发表年份&#xff1a;2023 3. 发表期刊&#xff1a;CVPR 4. 关键词&#xff1a;立体匹配、MVS、深度学习、高频信息、LSTM 5. 探索动机&#xff1a;(1)当涉及到估计的视差图的更精细的特征时&#xff0c;大多数当前…