ORM查询优化

only与defer查询优化

减轻数据库的压力

only:

only括号内放字段,查询结果是一个列表套一个个数据对象

这些数据对象点括号的字段属性不会再查询数据库,直接就是对象获取属性

也支持点击括号内没有的字段,但是每点击一次就会重新走一次数据库查询

缺点:效率极低

实例:

res = models.Book.objects.only('title')
#print(res)     #拿到对象  数据库语句只走一次
for i in res:
	print(i.title)  #拿到数据所有书名   走一次数据库语句
	print(i.price)  #走5次数据库查询语句,第1次是总体的查询语句,后面4条是4条书籍字段的语句

defer:

实例:

res = models.Book.objects.defer('title')
#print(res)   #打印的结果是列表套对象,走一条数据库语句
for i in res:
	print(i.title) #走5次数据库查询语句,第1次是总体的查询语句,后面4条是4条书籍字段的语句
	print(i.price)  #点price 走一次数据语句 

总结:only与defer互为反关系

defer括号内放什么字段 查询出来的对象就没有该字段

如果你要点击 每点击一次就要重新走一次数据库

而你如果点击了非括号内的字段 就不会走数据库 仅仅是对象属性的操作

select_related与prefetch_ralated

实例:

res = models.Book.objects.all()
#print(res)    #只走一次数据库语句
for i in res:
print(i.title)  #只走一次数据库语句
print(i.publish)  #正向查询(按字段)    #走5次数据库查询语句,第1次是总体的查询语句,后面4条是4条出版社字段的语句   #多次查询会对数据库造成压力

实例:使用select_related优化实例

特点:

  1. select_related括号内只能放外键字段,并且外键字段的类型只能是一对多 或者 一对一 不能是多对多的
  2. 内部是自动联表操作 会将括号内外键字段所关联的表与当前表自动拼接成一张,然后将表中的数据一个个查询出来封装成一个个的对象
  3. 可以放多个外键字段,逗号隔开,会将多个外键字段关联表与当前的表拼成一个大的表
  4. 类似于left join , right join

优点:

跨表不用重复走数据库语句 ,减轻数据库的压力

res = models.Book.objects.select_related('publish')
#print(res)    # 走一条数据库语句
for i in res:
print(i.title)   # 走一条数据库语句
print(i.publish)  # 走一条数据库语句

prefetch_ralated:

特点:

  1. prefetch_ralated内部是子查询,会自动帮你按步骤查询多张表,然后将程序的结果封装到对象中,给用户的感觉还是联表操作
  2. 括号内支持传多个外键字段,没有类型限制,可以是多对多字段,每放一个外键字段,就多走一条sql语句,就多查询一张表

实例:

res = models.Book.objects.prefetch_related('publish','authors')
#print(res)    # 走两条数据库语句
for i in res:
print(i.title)   # 走两条数据库语句
print(i.publish)  # 走两条数据库语句

区别:

select_related 耗时:在联表上

prefetch_related 耗时: 查询的次数上 上千张表推荐使用

MTV与MVC模型

MTV:django自称是MTV框架,本质是MVC框架

MTV:可以拆分成

M:models

T:templates

V:views

MVC:

M:models

T:templates

C: controllar 路由匹配

choices参数

在将choices参数之间,我们先来回顾一下Django ORM创建表类中字段如何创建的把,是不是下面这样

# 举例这是一张用户基本信息表
class UserInfo(models.Model):
    username = CharField(max_length=32)
    age = IntegerField() # 整型字段不要传max_length参数哦----特别注意
    gender = CharField(max_length=2)# 用户性别

通过上面的userinfo表,我们是否可以想一下,在用户性别字段中,人类的性别好像只有两种表示方式,男/女,那这样,我们如果有100万条用户信息,而这100万条用户的性别就这么巧有90万都是女。

这个时候,就造成了问题,既然我们这个字段的描述信息,只需要两种描述就能完成这个用户字段在性别的描述,我们为什么不想一种方便简洁的形式去描述每一个用户的性别呢?

这个时候,不知道还是否记得,有没有什么数据类型是只有两种表现形式的呢?(布尔值?),没错就是布尔值,布尔值大家是否还记得(0:false / 1:True)。

这是一种方法,但是在这种情况下,很遗憾我们不需要用布尔值这种方式,这就引出了choices参数

我们依然是用数字来记录gender这个用户性别字段的描述,大家学过数据库就知道,能用整型存储的信息,为什么要用字符型呢?很明显,是因为整型比字符型占的空间小。

注意:并不是所有的这种仅仅用几个描述就能完成队大量数据的描述,都去用数字的,此处只是用gender字段为例!!

choices 参数的概念:它是一种以列表 / 元组的型式,里面嵌套着少数几个小元组的方式,表示一种对应关系

Ajax简介

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

Ajax = 异步 JavaScript 和 XML 或者是 HTML(标准通用标记语言的子集)。

Ajax 是一种用于创建快速动态网页的技术。

Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

优点:通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。(这一特点让用户感觉在不知不觉中完成请求响应的过程)

XML也是一门标记语言

该语法应用场景

  1. 写配置文件

  2. 可以写前端页面(odoo框架中 erp)

    每家公司都会有属于自己公司独有的内部管理软件,专门用来开发企业内部管理软件 框架 odoo

    odoo框架内部功能实现全部依赖于python2

    薪资计算

我们在学的时候只学JQuery封装好的方法 不需要掌握原生js版本在使用的时候一定要先导入jQuery括号内记得手动输入一个大括号: $.ajax({ })

ajax基本语法:

$.ajax({
	url:'',    //数据提交的后端地址,不写就是往当前页面提交,也可以写后缀,全称,跟actions一样
    type:'post', //提交方式  默认是get请求
    data:{'i1':$('#d1').val(),'i2':$('#d2').val()},   //提交的数据
    success:function(data){   //形参data就是异步提交之后后端返回结果
        $('#d3').val(data)    //回调机制需要做的事情
    }
})
一旦你使用了ajax 必知必会三板斧都不再作用于页面  而是与ajax交互
a标签href参数   get请求
form表单        get/post
ajax           get/post

前端和后端数据编码格式

前后端交互式一个数据编格式 针对不同的数据 后端会进行不同的处理

request.POST
request.FILES
  1. urlencoded
  2. formdata
  3. application/json
form表单发送数据的编码格式
Content-Type: application/x-www-form-urlencoded
  1. form表单默认的编码方式是urlencoded

    urlencoded所对应的数据格式
    					username=jason&password=123
    					django后端针对urlencoded数据 会自动解析并且帮你封装到request.POST中
    
  2. form表单发送文件 编码格式Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhjKCHQHDmcE62iMQ

    针对formdata格式的数据,你在浏览器上是无法看到的

    django后端只要你的数据满足urlencode格式
    username=jason&password=123
    就会自动帮你解析到request.POST中
    如果你是一个文件对象django后端也会自动识别帮你放到request.FILES中
    
  3. form表单无法发送json格式的数据 你要想传 你只能借助于ajax

ajax发送json格式数据

ajax发送数据的编码格式
ajax能够发送
urlencoded
formdata
application/json
Content-Type: application/x-www-form-urlencoded; charset=UTF-8ajax默认的编码格式也是urlencoded 也就意味着后端django也是将数据解析到request.POST中

在涉及到前后端交互的时候 你一定要做到数据的格式与编码格式一致

千万不要欺骗人家 数据是一种格式 请求头里面是另外一种格式

ajax发送json数据格式

dumps        stringify
loads         parse
Content-Type: application/json
{"username":"jason","password":"123"}

django后端针对json格式的数据 不会做任何的处理 数据怎么来的 只会原封不动的放到request.body中,需要自己动手处理

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            contentType:'application/json',  # 1.注意点1
            data:JSON.stringify({'username':'jason','password':'123'}),  # 2.注意点2
            success:function (data) {
                alert(123)
            }
        })
    })

ajax发送文件格式数据

借助于内置对象 new

该对象既可以携带文件数据 同样也支持普通的键值对

 $('#d1').click(function () {
				// 先生成一个内置对象
				var MyFormData = new FormData();
				//1.先添加普通的键值对
				MyFormData.append('username','json')//添加了一组普通的键值对
				MyFormData.append('password','123');
				//2.添加文件数据
				MyFormData.append('myfile',$('#d2')[0].files[0];)//如何获取input框中文件对象$('#d1')[0].files[0];)
				
$.ajax({
    url:'',
    type:'post',
    data:MyFormData,  # 1
	//发送文件必须要指定的两个参数
    contentType:false//不适用任何编码 MyFormData对象内部自带编码 django后端能够识别 # 2
    procesData:false,//不要处理数据  #3
    success:function(data){
    
    }
    })
})

序列化

drf  django restframework
		from app01 import models
		from django.core import serializers
		# 序列化目的  将数据整合成一个大字典形式 方便数据的交互
		def zzz(request):
			user_queryset = models.User.objects.all()
			# [{username:...,password:...,hobby:...,},{},{},{}]
			# user_list = []
			# for data in user_queryset:
			#     user_list.append(
			#         {'username':data.username,
			#          'password':data.password,
			#          'gender':data.get_gender_display(),
			#
			#          }
			#     )
			res = serializers.serialize('json',user_queryset)
			return HttpResponse(res)

循环链表

循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。

(1)单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可。

(2)多重链的循环链表——将表中结点链在多个环上。

优点:从表中任意一结点出发均能可找到表中的其他结点

判断空链表条件是:

head==head->next;

rear==rear->next;

尾指针

尾指针rear表示的单循环链表对开始结点a1和终端结点an查找时间都是O(1)。而表的操作常常是在表的首尾位置上进行,因此,实用中多采用尾指针表示单循环链表。带尾指针的单循环链表可见下图。

实例:在链表上实现两个线性表(a1...an)和(b1...bn)连成一个线性表(a1...an,b1...bn)的运算

LinkListConnect(LinkListA,LinkListB)
{//假设A,B为非空循环链表的尾指针
LinkListp=A->next;//①保存A表的头结点位置
A->next=B->next->next;//②B表的开始结点链接到A表尾
free(B->next);//③释放B表的头结点
B->next=p;//④
returnB;//返回新循环链表的尾指针
}

注意:循环链表中的指针没有NULL

注意:由于循环链表中没有NULL,故涉及遍历操作时,其终止条件就不再像非循环链表那样判断p或p->next是否为空,而是判断他们是否等于头指针

循环条件:

  单链表                  单循环链表
p! = NULL              -> p!= L
p!->next! = NULL       -> p->next! = L

最后一个结点是指向头指针的