ORM查询优化、ORM事务操作、ORM相关字段类型及参数

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:主表一般是指在一对一、一对多中一的那一方,当对其进行删除时,另外一张表的所有元素都应该受到影响
"""

posted @ 2023-01-02 19:34  知了了了了  阅读(77)  评论(0编辑  收藏  举报