数据库设计三大范式
第一范式(1NF):列不可再分(原子性)
每一列属性都是不可再分的,两列的属性相近或相似或一样,应尽量合并属性一样的列,确保不产生冗余数据。
第二范式(2NF):属性完全依赖路主键(唯一性)
第二范式是在第一范式的基础上建立起来的,也就是第二范式要求数据库表中的每个实例或行必须可以被唯一的区分,也就是一张表至少有一个主键来区分每一条记录。
第三范式(3NF):属性不依赖于其他非主键属性,属性直接依赖于主键(冗余性)
不同的属性之间不能有传递关系,也就是每一个属性的数据不能相互影响。
orm相关的数据库查询优化
惰性查询
惰性查询指当我们只查数据库而不是用这些数据时,Django不会执行查询数据库的代码,目的是减少不必要的数据库操作,降低数据库的压力。
如:
res = models.Book.objects.all()#只有当我们使用res时才会执行数据库查询的操作
all、only与defer
all
拿到自己的所有的属性,但是没有与其他表建立外键的属性。
only
only括号内放字段,查询结果是一个列表套一个个数据对象,这些数据对象点括号内的字段属性,不会再查数据库,直接就是对象获取属性;也支持点其他属性,但是其他属性会每拿一条数据就走一次数据库。
res = models.Book.objects.only('name')#查询一次
print(res)
for i in res:
print(i.name)
res = models.Book.objects.only('name')#查询多次
print(res)
for i in res:
print(i.price)
defer
defer与only是互为反操作,点括号内的属性会每拿一条数据就走一次数据库,点其他的属性反而只走一次数据库。
res = models.Book.objects.defer('name')#查询多次
print(res)
for i in res:
print(i.name)
res = models.Book.objects.defer('name')#查询一次
print(res)
for i in res:
print(i.price)
select_related与prefetch_related
select_related
括号内只能放一对一、一对多的外键字段,特点:内部自动连表操作,会将括号内外键字段所关联的表与当前表自动拼接成一张表,然后将表中的数据一个一个查询出来封装成一个一个的对象。
这样做的好处:跨表查询也不需要重复走数据库,减轻数据库压力。select_related()括号内放多个外键字段,逗号隔开,会将多个外键字段关联的表与当前表拼成一张大表。
耗时:数据库层面连表操作,当数据库特别大时可能连表的时间会长一点,用prefetch_related可能会好一点,但如果表比较小两者基本没太大差别。
res = models.Book.objects.select_related('publisher')
for i in res:
print(i.publisher.publisher_name)
prefetch_related
prefetch_related内部是子查询(当一个查询是另一个查询的条件时,称之为子查询。),特点:按步骤查询多张表,然后将查询结果封装到对象中,给用户的感觉好像还是连表操作,括号内支持传多个外键字段,每放一个外键字段就会多走一条SQL语句,多查一张表。
使用:主要用于多对多字段和一对多字段
耗时:查询的次数上
res = models.Book.objects.prefetch_related('publisher')
for i in res:
print(i.publisher.publisher_name)
MTV与MVC模型
MTV(models templates views)
models templates views:模型层、模板层、视图层
Django自称是MTV框架,其实本质还是MCV
MCV(models views controllar)
models views controllar:模型层、视图层、控制层
controllar指url(路由匹配)
choices参数
choices参数指一个字段只有几个情况可以选择,比如性别字段只有两个情况,类似的还有在职状态、学历、婚否等。
我们可以用0、1等数字代表男女等字段可能的情况,将数字存入表中(可以是数字也可以是字符串,通常用-1表示数据短缺或者数据丢失),取出的时候如果存储的数字在提前定义好的关系中会,则会取出对应关系的字符串,如果没有对应关系,取出的还是数字。
choices字段类型在获取值的时候统一句式:get_字段名_display()
class User(models.Model):
username = models.CharField(max_length=64)
password = models.IntegerField()
gender_choices = (
(1,'男'),
(2,'女'),
(3,'其他'),
)
gender = models.IntegerField(choices=gender_choices)
Ajax(重要)
AJAX简介
AJAX(Asynchronous Javascript And XML)“异步的Javascript和XML”,即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX的应用场景
搜索引擎根据用户输入的关键字,自动提示检索关键字,网站注册时候的实时用户名的查重,特点:
- 不刷新页面的前后端数据交互
- 异步操作,当请求发出后,浏览器还可以进行其他操作
AJAX前的知识储备
XML简单介绍
XML是一门标记语言,它的应用场景有:
1.写配置文件
2.写前端页面如odoo框架(公司内部管理软件开发框架,内部功能的实现全部依赖于python2)中的erp。
JSON简介
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
前端JAON对象与Python json模块的对应关系:
stringfy和parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象(json只认双引的字符串格式)
JSON.parse('{"name":"ylpb"}');
JSON.parse('{name:"ylpb"}') ; // 错误
JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"Tonny"})
经过json序列化的数据以字符串的数据类型存储的,这点是必须要清楚的,如
b = json.dumps({'password': 123})
print(type(b))
#<class 'str'>
print(b)
#{"password": 123}
#这点容易造成误解因为我们看到的好像并不是一个字符串
ajax基本语法结构:
$.ajax({
url:'', // 数据提交的后端地址 不写就是往当前页面提交 也可以写后缀 也可以写全称 跟actions一样
type:'post', // 提交方式 默认是get请求
data:{'i1':$('#d1').val(),'i2':$('#d2').val()}, // 提交的数据
success:function (data) { // 形参data就是异步提交之后后端返回结果
$('#d3').val(data) // 回调机制需要做的事情
}
})
前后端传输数据的编码格式
前后端进行数据交互的时候,针对不同的数据后端会进行不同的处理,Django中的request.POST、request.GET、request.FILES
前端向后端发送数据的时候需要指定数据编码格式,目前我们需要了解的有三种:urlencoded、formdata、json
form表单向后端发送数据的编码格式有两种,第一种是我们没有配置enctype时,它默认的编码格式是urlencoded,当我们发送文件时需要将enctype设置成 multipart/form-data,这样form表单发送文件的时候就采用formdata的格式进行编码。但是问题来了前端如何向后端发生json格式的数据呢?这个时候只能借助于AJAX才能完成json格式数据的发送,AJAX可以发送上述的三种编码格式的数据
AJAX如何传输json数据
前端代码:
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
contentType:'application/json', # 1.注意点1
data:JSON.stringify({'username':'ylpb','password':'123'}), # 2.注意点2
success:function (data) {
alert(123)
}
})
})
说明:
1.需要设置contentType:'application/json'。
2.对JSON数据进行序列化。
3.Django后端针对json格式的数据不会做任何的处理,只是将数据原封不动的放在了request.body中,我们需要手动对其进行反序列化处理。
AJAX发送文件
<form action="">
username:<input type="text" name="username">
password:<input type="text" name="password">
myfile:<input type="file" name="myfile" id="d2">
</form>
<button id="d1">点我发送文件数据</button>
<script>
// 传文件
$('#d1').click(function () {
// 先生成一个内置对象
var MyFormData = new FormData();
// 1. 先添加普通的键值
MyFormData.append('username','ylpb'); // 添加了一组普通的简直对,append后面第一个参数是键,第二个参数是值
MyFormData.append('password','123');
MyFormData.append('hobby',['read','run']);
// 2. 添加文件数据MyFormData.append(文件名,文件数据)
MyFormData.append('myfile',$('#d2')[0].files[0]); // 获取input框中文件对象的方法:$('#d2')[0].files[0] 方法介绍:找到id为d2(input框的id)的jQuery对象$('#d2'),然后索引0拿到标签对象即$('#d2')[0],然后使用files方法获取文件数据
$.ajax({
url:'',
type:'post',
data:MyFormData,
// 发送文件必须要指定的两个参数
contentType:false, // 不使用任何编码 MyFormData对象内部自带编码 django后端能够识别
processData:false, // 不要浏览器处理数据
success:function (data) {
}
})
})
</script>
Django后端可以自动识别MyFormData(我们自己生成的内置对象)中的普通键值和文件,普通键值放在request.POST里面,文件放在request.FILES里面。
序列化
序列化的目的就是将数据整合成一个大的字典的形式方便数据交互。
Django内置的serializers模块
前端想拿到通过orm查到的一个个对象,(数据库里的一条条记录),后端想把直接实例化出来的对象发送给前端,这时候就需要用到Django给我们提供的序列法方式(其实就是列表套字典的形式将数据发送出去)。
使用方法:
def ser(request):
#拿到用户表里面的所有的用户对象
user_list=models.User.objects.all()
#导入内置序列化模块
from django.core import serializers
#调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
ret=serializers.serialize('json',user_list)
return HttpResponse(ret)