ORM查询优化、ORM事务操作、ORM相关字段类型及参数
ORM查询优化
ORM的查询默认都是惰性查询且自带分页处理。
若需要做SQL,最好加上LIMIT分页。
# only与defer
res = models.Book.objects.all()
# 获取所有的[数据对象1,],不走sql语句
只想拿某些字段的话,使用value,但是value拿到的是数据[{},{},{}]。只有only可以实现获取对象。
1.only
'''数据对象+含有指定字段对应的数据'''
# 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查询
"""
only会将括号内填写的字段封装到数据对象中,后续获取不走SQL,但是获取括号内没有的字段数据则需要走SQL。
"""
2.defer
res = models.Book.objects.defer('title', 'price')
# print(res) # queryset [数据对象、数据对象]
for obj in res:
# print(obj.title) # 点击括号内填写的字段 走SQL查询
# print(obj.price)
print(obj.publish_time)
# 点击括号内没有的字段获取数据 不走SQL查询
"""
defer会将括号内填写的字段封装到数据对象中,后续获取有字段需要走SQL,但是获取括号内没有的字段数据则不需要走SQL。
"""
# select_related与prefetch_related
括号内都是只支持一对一和一对多外键字段,多对多外键字段是不支持的。
1.select_related 连表操作
res = models.Book.objects.all()
# for obj in res:
# print(obj.publish.name) # 每次查询都需要走SQL
"""
通过点book外的表,每次查询都会走SQL;如果不想走SQL,可以将两个表连起来后再查询不走SQL语句。
"""
res = models.Book.objects.select_related('authors')
# 先连表后查询封装
res1 = models.Author.objects.select_related('author_detail')
# 括号内不支持多对多字段,其他两个都可以
# print(res1)
# for obj in res:
# print(obj.publish.name) # 不再走SQL查询
"""
select_related括号内填写一对多、一对一字段,自动连表然后继续数据封装。
"""
2.prefetch_related 子查询
res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
print(obj.publish.name)
"""
prefetch_related括号内填写一对多、一对一字段 基于子查询然后封装数据
"""
ORM事务操作
事务四大特性:
原子性、一致性、隔离性、持久性
相关SQL关键字:
start transaction;
rollback;
commit;
savapoint;
相关重要概念:
脏读、幻读、不可重复读、MVCC多版本控制
# django orm提供了至少三种开启事务的方式
# 方式一:全局开启事务
1.配置文件数据库(DATABASE)相关添加键值对 (全局有效)
2."ATOMIC_REQUESTS":
True每次请求所涉及到的orm操作同属于一个事务
"""
若过程中报错了,就会往回滚。
"""
# 方式二:装饰器(局部有效)
from django.db import transaction # 引入事务模块
@transaction.atomic # 原子装饰器
def index():pass
eg:
from django.db import transaction
@transaction.atomic
def index():
model.book.objects.create(title='西游记',price='888',publish_id=1)
hhshhsldlllds # 报错>>>就会过滚
return HttpResponse('添加成功')
return 123 # 在事务里面,这也算成功
"""
装饰器针对的是视图函数,当视图函数需要设计ORM操作,若函数自上往下执行,遇到报错会自动回滚到视图函数开始的状态。
"""
# 方式三:with上下文管理(局部有效)
from django.db import transaction
def reg():
with transaction.atomic():
pass # 这下面看作是同一个事务处理,遇到报错就会回滚
ORM常用字段类型
1.AutoField(primary_key)
# 字段才用,可以让它自动创建
2.CharField(max_length)
# 对应varchar字段,存储有限的字符
3.IntegerField # 整型
4.BigIntergerField #整型(比如手机号11位)
5.DecimalField(max_digits,decimal_places) # 小数字段
6.DateField(auto_now,aoto_now_add) # 日期(年月日)
7.DateTimeField(auto_now auto_now_add) #日期(年月日时分秒)
8.Booleanfiels
# 传布尔值自动存0(False)或者1(True)
9.TextField # 存储大段文本
10.EmailField # 存储邮箱格式数据
11.FileField
# 传文件对象,自动保存到提前配置好的路径下并存储该路径信息
12.ForeignKeyField(to='',on_delete)
# 实际外键字段,建立一对一关系
13.OneToOneField(to='',on_delete)
# 实际外键字段,建立一对多关系
14.ManyToManyField(to='')
# 虚拟外键字段,建立多对多关系
"""
注意:
这些orm字段并非和sql字段一一对应,有些是封装了一些逻辑功能在字段的创建、存储过程中的。
"""
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常用字段参数
1.primary_key # 主键字段
2.verbose_name # 字段注释
3.max_length # 字段长度
4.max_digits # 小数总共多少位
5.decimal_places # 小数点后面的位数
6.auto_now # 每次操作数据自动更新事件
7.auto_now_add
# 首次创建自动更新事件后续不自动更新
# 在时间相关字段的独有参数,设置为True则会自动执行相关功能。
8.null # 允许字段为空
9.default # 字段默认值
10.unique # 唯一值
11.db_index # 给字段添加索引
12.choices # 当某个字段的可能性能够被列举完全的情况下使用
# eg:性别、学历、工作状态...
class User(models.Model):
name=models.CharField(max_length=32)
info= MyCharField(max_length=64)
# 提前列举好对应关系
gender_choice=(
(1,'男性'),
(2,'女性'),
(3,'其他'),
)
gender = models.IntergerField(choices=gender_choice,null=True)
user_obj = User.objects.filter(pk=1).first()
# 拿到一个对象
user_obj.gender
# 直接点显示存储的真实数据
user_obj.get_gender_display()
# 通过这个方法拿显示转义后的选项
外键相关参数
to # 关联表
to_field # 关联字段(不写默认关联数据主键)
on_delete
# 当删除关联表中的数据时,当前表与其关联的行的行为。(只针对一对多和一对一关系)
# 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相似
"""
ps:主表一般是指在一对一、一对多中一的那一方,当对其进行删除时,另外一张表的所有元素都应该受到影响
"""