目录
一, ORM 查询优化
1. all() 查询
2.
only()/defer() 方法
(1)only() 方法
(2)defer() 方法
- 3.
- select_related()/prefetch_related()
- (1)select_related()
- (2)prefetch_related()
- (3)
- select_related()/prefetch_related()
的优缺点
二, MTV 与 MVC 模型
1. MTV 模型
2. MVC 模型
三, chioces 参数
四, Ajax
1. Ajax 语法
(1) 起手语法
(2)Ajax 基本语法结构
五, 前端传输数据的编码格式
1. 常见的编码格式
2. form 表单发送数据的编码格式
(1)urlencoded 编码格式
(2)formdata 编码格式
(3)JSON 格式
3. Ajax 发送数据的编码格式
(1)urlencoded 编码格式
(2)formdata 编码格式
(3)application/JSON 编码格式
六, 后端数据的序列化
一, ORM 查询优化
遵循能少走一次数据库就少走一次, 即一次查询操作中能少用 SQL 查询语句就尽量少用.
1. all() 查询
惰性查询 减少不必要的数据库操作 降低数据库的压力
- res = models.Book.objects.all()
- # 针对这行代码, 如果不使用 res, 则不会执行数据库查询的.
- 2.
only()/defer() 方法
(1)only() 方法
only() 括号内放字段 查询结果是一个列表套一个个的数据对象, 即 queryset 对象.
这些数据对象点括号内的字段不会再查询数据库, 直接就是对象获取属性
也支持点括号内没有的字段, 但是每点一次就会重新走一次数据库查询, 此时查询效率极低.
实例
- res = models.Book.objects.only('title')
- print(res)
- for i in res:
- print(i.title) # 只会走最初的那一次, 这行不走数据库
- print(i.price) # 除了最初查询走的那一次, 每到这一行都会再走一次数据库进行查询
(2)defer() 方法
defer() 与 only() 是互为反操作
defer() 括号内放什么字段 查询出来的对象就没有该字段属性
如果你要对象点括号内的字段, 每点一次就要重新走一次数据
而你如果点击了非括号内的字段, 就不会走数据库, 仅仅是对象点属性的操作
实例
- res = models.Book.objects.defer('title')
- print(res)
- for i in res:
- print(i.title) # 除了最初查询走的那一次, 每到这一行都会再走一次数据库进行查询
- print(i.price) # 只会走最初的那一次, 这行不走数据库
- 3.
- select_related()/prefetch_related()
- (1)select_related()
select_related 原理是联表查询
select_related 括号内只能放外键字段 并且外键字段的类型只能是一对多 或者 一对一 不能是多对多
内部是自动联表操作, 会将括号内外键字段所关联的表, 与当前表自动拼接成一张表
然后将表中的数据一个个查询出来封装成一个个的对象, 这样做的好处就在于跨表也不需要重复的走数据库了, 减轻数据库的压力
select_related 括号内可以放多个外键字段, 逗号隔开, 会将这些外键字段关联的表与当前表全部拼成一张大表
耗时: 主要在联表时耗时 (数据库层的操作)
实例
- res = models.Book.objects.select_related('publish') # publish 为外键字段
- print(res)
- for i in res:
- print(i.title) # title 为普通字段 , 只是对象点属性获取属性值, 不走数据库
- print(i.publish) # 只是对象点属性获取属性值, 不走数据库
- (2)prefetch_related()
prefetch_related 原理是子查询
自动帮你按步骤查询多张表, 然后将查询的结果封装到对象中, 用户的感觉好像还是联表操作
括号内支持传多个外键字段, 并且没有类型限制
特点: 每放一个外键字段, 就会多走一条 sql 语句, 多查询一张表
耗时: 查询的次数上的耗时
实例
- res = models.Book.objects.prefetch_related('publish','authors') # publish 和 authors 都是外键字段, publish 是一对多的外键字段, authors 是多对多的建立第三张表的虚拟外键字段
- print(res)
- for i in res:
- print(i.title) # 只是对象点属性获取属性值, 不走数据库
- print(i.publish) # 只是对象点属性获取属性值, 不走数据库
- (3)
- select_related()/prefetch_related()
的优缺点
没有谁比谁好, 结合实际情况, 使用不同方法.
如两张表都太大时, 联的表时会把不需要的一些数据行也连接在一起成一张大表, 不但消耗更多的时间, 也浪费内存, 因为联表是数据库层的操作, 所以还会增加数据库的负担. 此时, 用 prefetch_related() 方法更好.
二, MTV 与 MVC 模型
这两个东西都是纯理论, 没有特别的意思.
1. MTV 模型
- MTV
- M:models
- T:templates
- V:views
django 自称为是 MTV 框架 本质其实还是 MVC
2. MVC 模型
- MVC
- M:models
- V:views
C:controllar 路由匹配
三, chioces 参数
chioces 参数的作用是把一些数据信息映射成一个简单的字符串或者数字, 在保存数据时只需要保存这些简单的字符串或数字即可, 以此可以节省数据库资源.
取值:
只要是 choices 字段类型, 在获取值的时候 统一句式:
get_字段名_display()
. 若直接以对象点字段的方式, 则获取到的是我们自定义 chioces 参数的值的每个元组中的第一个元素.
插入数据:
当我们在插入数据时, 若插入 chioces 参数的自定义值中没有的数据, 可以插入成功. 在使用
get_字段名_display()
取值时, 因为元组中没有第二个元素, 不会报错, 取值也只会取到第一个元素. 这里不是很好理解, 看下面的实例.
实例
- # models.py 文件中:
- class User(models.Model):
- username = models.CharField(max_length=64)
- password = models.IntegerField()
- # 自定义 chioces 参数的值, 一个元组就是一个值, 元组第一个元素可以为数字, 也可以为字符串, 以 gender 字段的字段类型为准.
- gender_choices = (
- (1,'男'),
- (2,'女'),
- (3,'其他'),
- )
- gender = models.IntegerField(choices=gender_choices) # chioces 参数
- # views.py 文件中:
- # 执行插入操作
- models.User.objects.create(username='tank',password=123,gender=1)
- models.User.objects.create(username='nick',password=123,gender=4) # 可以插入数据成功
- # 执行查询操作
- user_obj1 = models.User.objects.filter(username='tank').first()
- user_obj2 = models.User.objects.filter(username='nick').first()
- # 打印信息
- print(user_obj1.get_字段名_display()) # 结果是: 男
- print(user_obj2.get_字段名_display()) # 结果是: 4
四, Ajax
Ajax 不是一个新的语言, 他只是在原有的 JS 语言下, 封装的一个大的方法. 类似 python 中的装饰器.
Ajax 最大的作用是在不重新加载整个页面的情况下, 可以与服务器交换数据并更新网页的部分内容.(这一特点给用户的感受是在不知不觉中完成请求和响应过程)-
题外话:
每家公司都会有属于这家公司独有的内部管理软件
专门用来开发企业内部管理软件框架 --》 odoo
odoo 框架内部功能实现全部依赖于 python2
1. Ajax 语法
(1) 起手语法
起手:
- $.Ajax({
- # 书写代码
- })
(2)Ajax 基本语法结构
- <scrip>
- $.Ajax({
- url:'', // 数据提交的后端地址 不写就是往当前页面提交 也可以写后缀 也可以写全称 跟 form 表单的 actions 参数一样
- type:'post', // 提交方式 默认是 get 请求
- data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 提交的数据
- success:function (recv_data) { // 形参 recv_data 就是异步提交之后后端返回结果
- $('#d3').val(recv_data) // 回调机制需要做的事情
- }
- })
- </scrip>
实例
- // 前端代码:
- $.Ajax({
- url:'', // 数据提交的后端地址 不写就是往当前页面提交 也可以写后缀 也可以写全称 跟 form 表单的 actions 参数一样
- type:'post', // 提交方式 默认是 get 请求
- data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 提交的数据
- success:function (recv_data) { // 形参 recv_data 就是异步提交之后后端返回结果
- $('#d3').val(recv_data) // 回调机制需要做的事情
- }
- })
- // 后端代码:
- def xxx(request):
- print(request.is_ajax()) # 判断当前请求是否是 Ajax 请求, 打印结果: True
- # print(request.POST) # Ajax 发送的 post 请求 普通的键值对也在 request.POST 中获取
- if request.is_ajax():
- i1 = request.POST.get('i1')
- i2 = request.POST.get('i2')
- res = int(i1) + int(i2)
- return HttpResponse(res) # 给异步回调函数 success
- # return render(request,'xxx.html') # 给异步回调函数 success
- # return redirect('https://www.baidu.com') # 给异步回调函数 success
- return render(request,'xxx.html')
注意: 一旦你使用了 Ajax,django 中必知必会三板斧 (
render/HttpResponse/redirect
) 都不再作用与页面, 而是与 recv_data 交互, 即这三个方法返回到前端的数据都被接收中 recv_data 中
五, 前端传输数据的编码格式
前端发到后端的数据都有数据编码格式, 针对不同的数据, 后端会自动进行不同的处理
前端中, 只要你的数据满足 urlencoded 格式, 不管你当前的编码格式是什么, django 后端都会自动解析, 并且根据你的提交方式帮你封装到
request.GET 或 request.POST
中
urlencoded 编码格式对应的数据的格式:
username=jason&password=123
1. 常见的编码格式
- urlencoded
- formdata
- application/JSON
2. form 表单发送数据的编码格式
form 标签的控制编码格式的属性: enctype
(1)urlencoded 编码格式
form 表单默认编码格式是 urlencoded
urlencoded 编码格式对应的数据格式:
username=jason&password=123
django 后端针对 urlencoded 数据, 会自动解析, 并且根据你的提交方式帮你封装到 request.GET 或 request.POST 中
(2)formdata 编码格式
传文件时用的编码格式
传文件必须做到两件事:
必须将其默认的 urlencoded 换成 formdata
提交数据方式改为 post
针对 formdata 格式的数据, 你在浏览器上是无法查看到, 因为这时的提交方式肯定是 post
如果你是一个文件对象, django 后端也会自动识别帮你放到 request.FILES 中
(3)JSON 格式
form 表单无法发送 JSON 格式的数据 你要想法 你只能借助于 Ajax.
3. Ajax 发送数据的编码格式
Ajax 能够发送 3 种格式的数据:
- urlencoded
- formdata
- application/JSON
(1)urlencoded 编码格式
Ajax 默认的编码格式也是 urlencoded 也就意味着后端 django 也是会自动解析, 并且根据你的提交方式帮你封装到
request.GET 或 request.POST
中
(2)formdata 编码格式
文件对象的数据, django 后端会自动识别并存放在 request.FILES 中
Ajax 传文件的实例:
牢记实例中的 1, 2, 3, 4 四点.
以下 MyFormData 添加的前 3 条数据在后端会自动存放在 request.POST 中, 最后一个文件数据会在后端自动存放在 request.FILES 中.
- <scrip>
- // 传文件
- $('#d1').click(function () {
- // 1. 先生成一个内置对象
- var MyFormData = new FormData();
- // 2. 先添加普通的键值
- MyFormData.append('username','jason'); // 添加了一组普通的键值对
- MyFormData.append('password','123');
- MyFormData.append('hobby',['read','run']);
- // 3. 添加文件数据
- MyFormData.append('myfile',$('#d2')[0].files[0]); // 如何获取 input 框中文件对象 $('#d1')[0].files[0]
- // Ajax 基本语法结构
- $.Ajax({
- url:'',
- type:'post',
- data:MyFormData,
- // 4. 发送文件必须要指定的两个参数 (1)(2)
- contentType:false, // (1) 不适用任何编码 MyFormData 对象内部自带编码 django 后端能够识别
- processData:false, // (2) 不要处理数据
- success:function (back_data) {
- alert(back_data) // 回调机制需要做的事情
- }
- })
- })
- </scrip>
(3)application/JSON 编码格式
django 后端针对 JSON 格式的数据, 不会做任何处理, 数据怎么来的, 只会原封不动的放到 request.body 中, 需要你自己手动处理.(即到后端还是二进制类型的 JSON 格式的数据)
Ajax 传输 JSON 格式数据实例:
注意: 实例中的 1, 2 两点
- <scrip>
- $('#d1').click(function () {
- $.Ajax({
- url:'',
- type:'post',
- contentType:'application/json', // 1. 编码格式写法
- data:JSON.stringify({'username':'jason','password':'123'}), // 2. 序列化
- success:function (back_data) {
- alert(back_data)
- }
- })
- })
- </scrip>
后端对前端的 Ajax 传输过来的 JSON 格式的数据的反序列化
- # 因为 Ajax 传输过来的 JSON 格式的数据是二进制类型的 JSON 格式, 所以:
- # 方式一:
- import JSON
- json_data = ajax_data.decode('utf-8')
- data = JSON.loads(json_data)
- # 方式二: 直接使用 JSON.loads , 他会直接把二进制也一起转.
- data = JSON.loads(ajax_data)
六, 后端数据的序列化
在实际开发环境中, 针对前后端分离的模式, 因为此时不能使用 django 的模板语法, 后端返回到前端的数据需要非常多, 非常清晰, 并且是 JSON 格式的数据. 如: 要返回当前数据来自哪张表, 数据要有描述即字典类型, 还有等等, 我们此时就需要自己手动书写, 这样就会非常麻烦, 也不保证没有缺漏的数据.
针对上面的问题, 通过 django 中的内置模块 serializers 就可以完美解决了.
实例:
- from app01 import models
- from django.core import serializers
- # 序列化目的 将数据整合成一个大字典形式 方便数据的交互
- def zzz(request):
- user_queryset = models.User.objects.all()
- res = serializers.serialize('json',user_queryset)
- return HttpResponse(res)
来源: http://www.bubuko.com/infodetail-3309277.html