目录
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)
查询条件的左侧 能够将查询条件的左侧由变量名或字段名变字符串
先用Q产生一个对象 而Q其实就一个类 类加括号就是在实例化对象 那么q_obj就成查询条件了 默认是and关系
那么也支持改成or关系
这样就可以实现与用户交互 前端返回的是字符串类型 就可以编写简易的搜索框查询功能
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) # queryset [数据对象、数据对象]
for obj in res:
# print(obj.title) # 点击括号内填写的字段 走SQL查询
# print(obj.price)
print(obj.publish_time) # 点击括号内没有的字段获取数据 不走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('authors') # 先连表后查询封装
# res1 = models.Author.objects.select_related('author_detail') # 括号内不支持多对多字段 其他两个都可以
# print(res1)
# for obj in res:
# print(obj.publish.name) # 不再走SQL查询
res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
print(obj.publish.name)
1.ORM的查询默认都是惰性查询
如上图中res都是灰色 没有执行 针对查询 只要不用 就不会执行这样就可以节省效率
用了就会执行
2.ORM的查询自带分页处理
当在查数据比较庞大的时候 假如有几亿条数据 那么在查询的时候就得做分页处理 ORM中查询是默认分页
PS:以后自己在写SQL的时候 在对一张表做查询 表数据比较庞大的时候 为防止崩溃 最好是加上limit做防范
3.only与defer
only
all就是把表里面所有的数据都封装到对象里面去 然后对象去点里面的数据就不用再走数据库查询
只执行了一条sql语句
那如果只想要书和价格呢?
用values拿指定字段对应的数据 那么得到的是列表套字典 并不能拥有对象点的方式
想要i能够点书名和价格 结果报错 手里拿的字典没法点 报错
多个对象里面含有只有指定的多个字段数据 其他的没有 这时候就要用到only了
就是all与values结合 既拥有的all对象点的方式也拥有了values拿到指定字段的数据
如图得到的就是列表套对象
就能拿到指定的字段数据 点only括号内的不走sql
SQL也只执行了一次
点括号外的走SQL
将only括号里面的数据封装到对象里面 当在点括号里面的数据是不会走SQL查询 而如果是点的是括号里没有填写的字段 可以拿到数据 但每点一次 都会执行一次SQL数据库查询
defer
defer与only相反 括号内的走sql 括号外的不走
点defer括号里面的 就会走SQL查询
点defer括号外的其他字段 就不走SQL查询
4.select_related与prefetch_related
select_related 连表查询
如下图的查询是把书籍的数据封装到了对象中 书籍对象点其他除书以外其他的字段就每点一次就会得执行一次SQL查询
如何优化查询次数 以及查询时间呢?
用到select_related 连表查询
提前封装好了 就不用再走SQL查询了 也只走一句
不允许填写多对多虚拟字段 只能是一对一 一对多
否则报错
prefetch_related 子查询
外键字段不允许填写多对多虚拟字段 只能是一对一或一对多
res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
print(obj.publish.name)
把书所有的书籍先查出来基于书里面的publish_id再到出版社里面把对应数据查找出来
只会执行两条SQL 先执行一条把这一条的结果当做另外一条的条件 用的时候感觉不出来
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
三种开启事物的方式
settings配置中有 网址记录了数据库相关操作
方式1:配置文件数据库相关添加键值对
"ATOMIC_REQUESTS": True每次请求所涉及到的orm操作同属于一个事务
全局事物开启 全局有效
默认每一次请求所涉及到的orm操作同属于一个事务
要么都成功要么都失败
如下报错就会回滚
极限情况 :
当返回的不是一个response对象时 也是会执行成功的
只要到return就执行成功 即使会报错 表数据也添加成功了
方式2:装饰器
from django.db import transaction
@transaction.atomic
def index():pass
需要导一个transaction模块
局部有效 局部开启针对某个视图函数
被装饰器修饰的视图函数就属于一个事物
表数据添加成功
极限情况:
当返回的不是一个response对象时 也是会执行成功的
3.with上下文管理
局部有效 也是需要导一个transaction模块
with里面的报错自动回滚
如下图中在with里面报错就会自动回滚
添加成功:
ORM常用字段
AutoField
primary_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字段类型与原生SQL的对应
ORM字段参数
外键多了就增强了耦合度 就不一样解耦合 所以外键一般是靠代码逻辑来建立
primary_key 主键
verbose_name 注释
max_length 字段长度
max_digits 小数总共多少位
decimal_places 小数点后面的位数
auto_now 每次操作数据自动更新事件
auto_now_add 首次创建自动更新事件后续不自动更新
null 允许字段为空
default 字段默认值
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)
user_obj = 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相似
choices
当个某一个字段能够被完全的列举出来时
除里面指定的填啥就是啥
如下图填写的4就是4了 而1 2 3指定的就是男性 女性 其他
固定语法get_xxx_display()
Ajax请求
异步提交 局部刷新
场景:在没有点提交 都会自动校验
Async就是异步的意思
目前学的是jQuery版本
如下图 在点提交让它不刷新 原来的数据还在
必须要导:
写js代码
异步回调函数