57 Django模型层3与数据传输与Ajax
Posted 纳福川Donner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了57 Django模型层3与数据传输与Ajax相关的知识,希望对你有一定的参考价值。
目录
一、orm查询优化
能少走数据库就少走数据库。
1.only与defer
only:取对象,对象中只包含主键和only括号里的属性。
only括号内放字段,查询结果是一个列表套一个个的数据对象。
这些数据对象通过点的方式取括号内的字段属性不会再查询数据库,直接就是对象获取属性。只需要查一次数据库就可以全取出。
不过only也可以点击括号内没有的字段,但是每点击一次就会重新走一次数据库查询,效率极低。
res = models.Book.objects.only('title')
for i in res:
print(i.title) # 走一次
for i in res:
print(i.price) # 走11次,有几个对象走几次
defer:与only相反,排除括号内的字段。
defer与only是互为反操作。
defer括号内放什么字段,查询出来的对象就没有该字段属性。
如果你要点击括号内的对象,每点击一次就要重新走一次数据。
而你如果点击了非括号内的字段,就不会走数据库,仅仅是对象点属性取值的操作。
res = models.Book.objects.defer('title')
# print(res)
for i in res:
print(i.title) # 有几个对象走几次
for i in res:
print(i.price) # 走一次
2.select_related与prefatch_related
select_related:用来优化查询外键的操作。
select_related括号内只能放外键字段,并且外键字段的类型只能是一对多 或者一对一,不能是多对多。多对多会报错。
内部是join自动连表操作,会将括号内外键字段所关联的表与当前表自动拼接成一张表。
然后将表中的数据一个个查询出来封装成一个个的对象。
这样做的好处就在于跨表也不需要重复的走数据库了,减轻数据库的压力 。
select_related括号内可以放多个外键字段(不能是多对多),逗号隔开,会将多个外键字段关联的表与当前表通过sql语句的join方法全部拼成一张大表。
耗时:数据库层面需要先连表,耗时耗在连表需要的时间。
res = models.Book.objects.select_related('publisher')
for i in res:
print(i.title)
print(i.publisher)
prefatch_related:prefetch_related内部是子查询。
会自动帮你按步骤查询多张表 ,然后将查询的结果封装到对象中。
给用户的感觉好像还是连表操作。实际内部方法不一样。
括号内支持传多个外键字段,并且没有类型限制。
特点:每放一个外键字段,就会多走一条sql语句,多查询一张表。
耗时:查询的次数长,耗时耗在查询次数上。
res = models.Book.objects.prefetch_related('publisher','authors')
for i in res:
print(i.title)
print(i.publisher)
两者之间的优缺点:
需要结合实际情况,看表的大小。
在两张表都特别大的情况下,连表操作可能耗时更多。
二、模型层choices参数
choices参数是模型层中字段的参数,choices属性的值需要为一个提前定义的对应关系容器。
容器内写数字integerfield(也可以是字符charfield)与状态的对应关系,以元组的形式存在一个大元组里。
# models
class User(models.Model):
sex_choices = (
(1,'男'),
(2,'女'),
(3,'不愿透露'),
)
sex = models.IntegerField(choices=sex_choices)
# 该字段存数字
# 可以存提前定义好的关系中的数字,也可以存不在关系中的数字
# 但是取得时候,也可以正常取,但取的是数字
# test
# 字段中存choices字段类型时,如果想要取出数字对应的值需要用‘get_字段名_display()’方法来获取
user_obj = models.User.objects.get(pk=1)
user_obj1 = models.User.objects.get(pk=4)
# print(user_obj.gender)
# print(user_obj1.gender) # 可以正常取,但,是数字
# print(user_obj.get_gender_display())
print(user_obj1.get_gender_display()) # 没有对应关系,获取到的还是数字本身
三、MTV与MVC模型
1.MVC
MVC(Model View Controller 模型-视图-控制器)
是一种Web架构的模式。特点:把业务逻辑、模型数据、用户界面分离开来,让开发者将数据与表现解耦。
Model: 代表数据存取层,
View: 代表的是系统中选择显示什么和怎么显示的部分,
Controller: 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。
2.MTV
Django框架就是MTV结构的。其实本质还是MVC。
MTV(Model Templates View 模型-模板-视图):
1.Models:数据存取层。
该层处理与数据相关的所有事务: 如何存取、如何验证有效,是一个抽象层,用来构建和操作你的web应用中的数据,模型是你的数据的唯一的、权威的信息源。它包含你所储存数据的必要字段和行为。通常,每个模型对应数据库中唯一的一张表。
2.模板(templates):即表现层。
该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。模板层提供了设计友好的语法来展示信息给用户。使用模板方法可以动态地生成html。模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。
3.视图(views):业务逻辑层。
该层包含存取模型及调取恰当模板的相关逻辑。用于封装负责处理用户请求及返回响应的逻辑。视图可以看作是前端与数据库的中间人,他会将前端想要的数据从数据库中读出来给前端。他也会将用户要想保存的数据写到数据库。
3.区别
MVC中的View的目的是「呈现哪一个数据」,而MTV的View的目的是「数据如何呈现」。
也就是把MVC中的View分成了视图(展现哪些数据)和模板(如何展现)2个部分,而Contorller这个要素由框架自己来实现了,我们需要做的就是把(带正则表达式的)URL对应到视图就可以了,通过这样的URL配置,系统将一个请求发送到一个合适的视图。
四、Ajax简介
AJAX(Asynchronous javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(XML也是一门标记语言,当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
在前端页面中,Ajax句式非常简单,用jQuery可以很方便的实现:
// 使用jQuery之前先导入jQuery
// ajax基本语法结构
$.ajax({
url:'', // 数据提交的后端地址,不写就是往当前页面提交,也可以写后缀,也可以写全称,跟actions一样
type:'post', // 提交方式,不写默认是get请求
data:"{i1:$('#d1'),i2:$('#d2')}", // 提交的数据
success:function(backdata){ // 形参backdata就是异步提交之后后端返回结果
$('#d3').val(backdata) // 这里是回调机制需要做的事情
}
})
一旦使用了ajax,三板斧都不会再作用域页面,而是和回调函数做交互。
五、前后端传输数据编码格式
前后端交互时,不同数据的编码格式是不一样的。
比如说你用form表单提交数据的时候,传普通的input框的文本和file文件时,后端可以用request.POST/request.FILES 接收文本和文件。
那么后端为什么可以识别你传的是文本还是文件呢?
就是因为你传输不同数据时所使用的编码格式不一样。
1. 不同的编码格式
目前,我们需掌握的编码格式有三种:
- urlencoded (默认,文本)
- form-data (文件)
- application/json (json格式的数据)
2. 前端朝后端发送数据的请求方式
- a标签href参数:get请求
- form表单:get/post
- ajax:get/post
2.1 form表单发送数据编码格式
django后端只要你的数据满足urlencoded格式:username=tbw&password=123
就会自动帮你解析到request.POST中。
如果你是一个文件对象django后端也会自动识别帮你放到request.FILES中。
form表单无法发送json格式的数据。
默认格式
Content-Type: application/x-www-form-urlencoded(谷歌浏览器可以看)
form表单发送数据默认编码格式为:urlencoded。
此格式的形式为:username=tbw&password=123
django后端针对urlencoded数据 会自动解析并且帮你封装到request.POST中。
文件
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhjKCHQHDmcE62iMQ
form表单发送文件数据的编码格式为:form-data
此格式的形式:你在浏览器上是无法查看到
json
form表单无法发送json格式的数据。你只能借助于ajax。
2.2 ajax发送数据的编码格式
ajax能够发送:
1.urlencoded
2.form-data
3.application/json
三种格式的数据。
默认格式
编码格式为:urlencoded。
也就意味着后端django也是将数据解析到request.POST中。
ajax发送文件
编码格式为:form-data。
需要借助于内置对象:new FormData()
该对象既可以携带文件数据,也支持普通的键值对。
$('#d1').click(function () { // 先生成一个内置对象 var MyFormData = new FormData(); // 1. 先添加普通的键值 MyFormData.append('username','tbw'); // 添加了一组普通的键值对 MyFormData.append('hobby',['read','run']); // 2. 添加文件数据 MyFormData.append('myfile',$('#d2')[0].files[0]); // 如何获取input框中文件对象$('#d1')[0].files[0] $.ajax({ url:'', type:'post', data:MyFormData, // 发送文件必须要指定的两个参数 contentType:false, // 不适用任何编码 MyFormData对象内部自带编码 django后端能够识别 processData:false, // 不要处理数据 success:function (data) { } }) })
ajax发送json格式数据
ajax发送json格式数据的方式:
$('#d1').click(function () { $.ajax({ url:'', type:'post', contentType:'application/json', data:JSON.stringify({'username':'jason','password':'123'}), success:function (data) { alert(123) } })
Django后端接收json格式数据的方法:
# django后端针对json格式的数据不会做任何处理, # 数据怎么来的,只会原封不动的放到request.body中,也就是接收到的是二级制数据 json_bytes = request.body # 解码 # json_str = str(json_bytes,encoding='utf-8') json_str = json_bytes.decode('utf8') # 反序列化 json_dic = json.loads(json_str) # json_dic = json.loads(json_bytes) # 自动帮你解码加反序列化 print(json_dic,type(json_dic))
六、序列化(drf会用到)
目的:将数据整合成一个大字典形式,方便数据的交互。
使用serializers模块完成序列化。
from django.core import serializers
def zzz(request):
user_queryset = models.User.objects.all()
res = serializers.serialize('json',user_queryset)
return HttpResponse(res)
以上是关于57 Django模型层3与数据传输与Ajax的主要内容,如果未能解决你的问题,请参考以下文章