python之路52 ORM查询、ORM事务、查询优化、常用字段及参数、ajax方法
Q查询进阶操作
from django.db.models import Q
q_obj = Q() # 1.产生q对象
q_obj.connector = 'or' # 默认多个条件的连接是and可以修改为or
q_obj.children.append(('pk', 1)) # 2.添加查询条件
q_obj.children.append(('price__gt', 2000)) # 支持添加多个
res = models.Book.objects.filter(q_obj) #查询支持直接填写q对象
print(res)
ORM查询优化
1.ORM的查询默认都是惰性查询
2.ORM的查询自带分页处理
3.only与defer
'''数据对象+含有指定字段对应的数据'''
res = models.Book.objects.only('title','price')
print(res) # queryset [数据对象、数据对象]
for obj in res:
# print(obj.title) # 点击括号内填写的字段 不走SQL查询
# print(obj.price)
print(obj.publish_time) # 可以点击括号内没有的字段获取数据 但是会走SQL查询
res = models.Book.objects.defer('title','price')
# print(res) # [数据对象,数据对象,]
for obj in res:
# print(obj.title)
# print(obj.price)
print(obj.publish_time)
"""
only可以将括号里列举的字段封装到数据对象里面,当用对象点括号里面的字段时,只会执行一条SQL查询,但是如果点括号里面没有的字段,每拿到一条数据就执行一次SQL语句。
defer也可以将括号里列举的字段封装到数据对象里面,当用对象点括号里面的字段时,每拿到一条数据就执行一次SQL语句,如果点括号里面没有的字段,则只执行一条SQL查询
"""
4.select_related(连表查询、不支持多对多字段)与prefetch_related(子查询)
# res = models.Book.objects.all()
# for obj in res:
# print(obj.publish.name) # 每次查询都需要走SQL
# res = models.Book.objects.select_related('publish') # 先连表后查询封装
# res1 = models.Author.objects.select_related('author_detail') # 括号内不支持多对多字段 其他两个都可以
# print(res1)
# for obj in res:
# print(obj.publish.name) # 不再走SQL查询
# print(res)
res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
print(obj.publish.name)
ORM事务操作
"""
1.事务的四大特性(ACID)
原子性、一致性、隔离性、持久性
2.相关SQL关键字
start transaction;
rollback;
commit;
savepoint;
3.相关重要概念
脏读、幻读、不可重复读、MVCC多版本控制。。。。
"""
django orm 提供了至少三种开启事务的方式
方式1:配置文件数据库相关添加键值对 全局有效
"ATOMIC_REQUESTS":True每次请求所涉及到的orm操作同属于一个事务
方式2:装饰器 局部有效
from django.db import transaction
@transaction.atomic
def index():pass
方式3:with上下文管理 局部有效
from django.db import transaction
def reg():
with transaction.atomic():
pass
ORM常用字段类型
AutoField
parimary_key=True
Charfield
max_length
IntegerField
BigIntergerField
DecimalField
max_digits decimal_places
DateField
auto_now auto_now_add
DateTimeField
auto_now auto_now_add
BooleanField
传布尔值自动存0或1
TextField
存储大段文本
EmailField
存储邮箱格式数据
FileField
传文件对象 自动保持到提前配置好的路径下并存储该路径信息
ORM还支持用户自定义字段类型
class MyCharField(models.Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length = max_length
super().__init__(max_length=max_length,*args,**kwargs)
def db_type(self,connection):
return 'char(%s)' % self.max_length
class User(models.Model):
name = models.CharField(max_length=32)
info = MyCharField(max_length=64)
ORM常用字段参数
primary_key 主键值
verbose_name 注释
max_length 字段长度
max_digits 数字总共多少位
decimal_places 小数点后面的位数
auto_now 每次操作数据自动更新时间
auto_now_add 首次创建自动更新时间后续不自动更新
null 允许字段为空
default 字段默认值(一般为1)
unique 唯一值
db_index 给字段添加索引
choices 当某个字段的可能性能够被列举完全的情况下使用
性别、学历、工作状态、 。。。
class User(models.Model):
name = models.CharField(max_length=32)
info = MyCharField(max_length=64)
# 提前列举好对应关系
gender_choice = ((1, '男性'), (2, '女性'), (3, '其他'),)
gender = models.IntegerField(choices=gender_choice, null=True)
添加好表数据在console内执行
# from app01 import models
# user_obj = models.User.objects.filter(pk=1).first()
# user_obj.gender
# user_obj.get_gender_display()
to 关联表
to_field 关联字段(不写默认关联数据主键)
on_delete 当删除关联表中的数据时,当前表与其关联的级联的行为
1、models.CASCADE
级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
当主表中中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
什么都不做,一切都看数据库级别的约束,主数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
Ajax
异步提交 局部刷新
ajax不是一门新的技术并且有很多版本 我们目前学习的jQuery版本(版本无所谓 本质一样就可以)
基本语法
<script>
// 1.先获取两个框里面的数据
{#console(v1Val,v2Val)#}
//2.给按钮绑定点击事件
$('#subBtn').click(function () {
let v1Val = $('#d1').val();
let v2Val = $('#d2').val();
//3.发送ajax请求
$.ajax({
url: '',//后端地址 三种填写方式 与form标签的action一致
type: 'post',//请求方式 默认也是get
data: {'v1': v1Val, 'v2': v2Val}, //发送的数据
success: function (args) {// 后端返回结果之后自动触发 args接收后端返回的数据
$('#d3').val(args)
}
}
)
})
</script>
def ab_ajax_func(request):
if request.method == 'POST':
print(request.POST)
v1 =request.POST.get('v1')
v2 = request.POST.get('v2')
res = int(v1) + int(v2)
return HttpResponse(res)
# return HttpResponse('ajax好哟用用')
return render(request,'abAjax.html')
在此基础需要定义三个input框 绑定d1/d2/d3
Content-Type
1.urlencoded
ajax默认的编码格式、form表单默认也是
数据格式 xxx=yyy&uuu=ooo&aaa=kkk
django后端会自动处理到request.POST中
2.formdata
django后端针对普通的键值对还是处理到request.POST中但是针对文件会处理到request.FILES中
3.application/json
form表单不支持 ajax可以
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'name':'jason','age':18}), // 千万不要骗人家
contentType:'application/json',
success:function (args) {
alert(args)
}
})
})
</script>
后端需要从request.body中获取并自己处理
ajax携带文件数据
<script>
$('#d3').click(function(){
//1.先产生一个FormData对象
let myFormDataObj = new FormData();
//2.往该对象中添加文件数据
myFormDataObj.append('name','jason');
myFormDataObj.append('age',18);
//3.往该对象中添加文件数据
myFormDataObj.append('file',$('#d2')[0].files[0])
// 4.发送ajax请求
$.ajax({
url:'',
type:'post',
data:myFormDataObj,
// ajax发送文件固定的两个配置
contenType:false,
processData:false,
success:function(args){
alert(args)
}
})
})
ORM字段与MySQL字段对应关系
对应关系:
'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',
ORM字段与MySQL字段对应关系
如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看
在Django项目的settings.py文件中,在最后复制粘贴如下代码
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
补充:
除了配置外,还可以通过一点.query即可查看查询语句,具体操作如下: