Q查询进阶
import os def main(): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoday07.settings') import django django.setup() from app01 import models
# Q查询进阶操作 """左边的查询条件依次写入 字段名,变量名""" from django.db.models import Q q_obj = Q() # 1.产生一个对象 q_obj.connector = 'or' # 默认添加的多个查询条件是and关系,如此将其变为or关系 q_obj.children.append(('pk',1)) # 2.添加查询条件 q_obj.children.append(('price__gt',200)) q_obj.children.append('title_contains','三') # 模糊查询 res = models.Book.objects.filter(q_obj) # 查询直接支持填写q对象 print(res)
main()
ORM查询优化
# 1.orm查询默认都是惰性查询 - orm的查询语句在用一个变量接收,但是不打印结果就不会执行该语句,叫惰性查询 # 2.orm查询自带分页处理 - orm的查询语句在查询到结果数量很大时,就会自己分页以保证安全 - orm查询后台的sql语句: SELECT `app01_book`.`id`, `app01_book`.`title`,
`app01_book`.`price`, `app01_book`.`publish_time`,
`app01_book`.`publish_id` FROM `app01_book` LIMIT 21; args=() """orm查询的sql语句自带limit分页""" # 3.only与defer
# orm查询优化 '''拿所有数据对象''' res = models.Book.objects.all() # 结果是queryset [数据对象,数据对象] for obj in res: print(obj.title) # 三国演义 print(obj.price) # 998.00 '''拿到的数据对象是列表包字典的形式''' res = models.Book.objects.all().values('title','price') # 结果是queryset [{},{}] for i in res: print(i) # 结果是{'title': '三国演义', 'price': Decimal('998.00')} """结果是数据对象+含有指定字段对应的数据""" ''' only查询,可以将括号中列举的字段封装到数据对象里面, 使用括号里面的字段时不会再走数据库查询, 括号里面没有的字段会走数据库查询,也可以获取到 ''' # 1.only res = models.Book.objects.only('title','price') # print(res) # queryset [数据对象,数据对象] for i in res: print(i.title) # 三国演义 print(i.price) # 998.00 print(i.publish_time) # 2022-12-07 ''' defer查询与only相反, 点击括号里存在的字段名走数据库查询, 点击括号里不存在的不走数据库查询 ''' # 2.defer res = models.Book.objects.defer('title', 'price') # print(res) # queryset [数据对象,数据对象] for i in res: print(i.title) # 三国演义 print(i.price) # 998.00 print(i.publish_time) # 2022-12-07
# 4.select_related与prefetch_related
'''select_related底层是连表操作,可以支持先连表后在进行查询封装''' # 1.select_related res = models.Book.objects.select_related('authors') print(res) """
底层sql语句: SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`,
`app01_book`.`publish_time`, `app01_book`.`publish_id`, `app01_publish`.`id`,
`app01_publish`.`name`,`app01_publish`.`address` FROM `app01_book`
INNER JOIN `app01_publish` ON (`app01_book`.`publish_id` = `app01_publish`.`id`)
LIMIT 21; args=() """
'''括号内仅仅支持一对一,一对多的字段''' res1 = models.Author.objects.select_related('author_detail') print(res1) res2 = models.Book.objects.select_related('publish')
# 底层先连表后查询封装 for obj in res2: print(obj.publish.name) # 结果:北京出版社 南京出版社 西京出版社
'''prefetch_related底层是子查询,会把一条sql当作另一个查询的条件,''' # 2.prefetch_related 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多版本控制 https://www.cnblogs.com/juzijunjun/p/16936590.html # 4.orm开启事务的方式
# django orm提供了至少三种开启事务的方式 # 方式一:全局开启(配置文件数据库相关添加键值对) 当有请求过来时,Django会在调用视图方法前开启一个事务。如果请求却正确处理并正确返回了结果, Django就会提交该事务。否则,Django会回滚该事务 在数据库配置文件处添加 : "ATOMIC_REQUESTS": True DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mxshop', 'HOST': '127.0.0.1', 'PORT': '3306', 'USER': 'root', 'PASSWORD': '123', 'OPTIONS': { "init_command": "SET default_storage_engine='INNODB'", #'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", #配置开启严格sql模式 } "ATOMIC_REQUESTS": True, #全局开启事务,绑定的是http请求响应整个过程 "AUTOCOMMIT":False, #全局取消自动提交,慎用 }, 'other':{ 'ENGINE': 'django.db.backends.mysql', ...... } # 还可以配置其他数据
# 方式2:局部使用(用视图函数装饰器) from django.db import transaction @transaction.atomic def view_func(request): # This code executes inside a transaction.
orm语句 return 返回值 # 方式3:局部使用(with上下文管理) from django.db import transaction def view_func(request): # This code executes in autocommit mode (Django's default). print('66666')
with transaction.atomic(): #保存点 # This code executes inside a transaction. orm语句
return 返回值
orm常用字段类型
# 1.AutoField: 主键自增 primary_key=Ture # 如果没有主键自增,则会创建一个主键id # 2.IntegerField: 整型类型 Big,Small也是整型 # 3.CharField: 字符类型 max_length # 表示字符长度 verbose_name # 别名
# 4.DecimalField 小数相关类型 max_digits # 数字允许的最大位数有几位
decimal_places # 小数点后面有几位
# 5.DateField: 日期字段 auto_now # 每次数据更新都会更新时间字段 auto_now_add # 数据只会在第一次创建时记录时间 # 6.DateTimeField: 日期时间字段 auto_now # 每次数据更新都会更新时间字段 auto_now_add # 数据只会在第一次创建时记录时间 # 7.BooleanField: 传入布尔值自动存0或1 # 8.TextField: 可以存储一大段文本 # 9.EmailField: 存储邮箱格式数据 # 10.FileField: 传入文件对象,自动保存到提前配置好的路径下并存储该路径信息 """ORM还支持用户自定义字段类型"""
# 定义阶段 class MyCharField(models.Model): 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 首次创建自动更新事件后续不自动更新 # 8.null 允许字段为空 # 9.default 字段默认值 # 10.unique 唯一值 # 11.db_index 给字段添加索引 # 12.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) user_obj = User.objects.filter(pk=1).first() user_obj.gender user_obj.get_gender_display()
# 13.to 关联表 # 14.to_field 关联字段(不写默认关联数据主键) # 15.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相似
标签:models,res,08,publish,查询,orm,app01,print,django From: https://www.cnblogs.com/juzijunjun/p/16992690.html