17.Django(综合练习题、sql_mode、only_full_group_by、ORM加锁、ORM事务)
1、查看每个作者的姓名以及出版的书的最高价格
# 方式1:
ret = models.Author.objects.values('name').annotate(max_price=Max('book__price')).values('name', 'a')
print(ret)
# 方式2:
ret = models.Author.objects.annotate(max_price=Max('book__price')).values('name', 'max_price')
print(ret)
# 方式3:
ret = models.Book.objects.values('author__name').annotate(max_price=Max('price')).values('author__name', 'max_price')
print(ret)
2、查看作者id大于2的作者的姓名以及出版社的书的最低价格
# 方式1: 正向查询
ret = models.Book.objects.filter(author__id__gt=2).values('author__name').annotate(min_price=Min('price')).values('author__name', 'price')
print(ret)
# 方式2: 反向查询
ret = models.Author.objects.filter(id__gt=2).values('name').annotate(min_price=Min('book__price')).values('name', 'min_price')
print(ret)
3、查询作者id大于2或者作何年龄大于等于20岁的女作者的姓名以及出版的书的最高价格
# 方式1: 正向查询
ret = models.Book.objects.filter(Q(author__sex='female') & Q(Q(author__age__gte=20)|Q(author__id__gt=2))).values('author__name').annotate(max_price=Max('price')).values('author__name', 'max_price')
print(ret)
# 方式2:反向查询
ret = models.Author.objects.filter(Q(sex='female') & Q(Q(age__gte=20) | Q(id__gt=2))).values('name').annotate(max_price=Max('book__price')).values('name', 'max_price')
print(ret)
4、查询每个作者出版的书的最高价格的平均值
# 方式1:正向查询
ret = models.Book.objects.values('author__name').annotate(max_price=Max('price')).values('max_price').aggregate(avg_price=Avg('max_price'))
print(ret)
# 方式2:反向查询
ret = models.Author.objects.annotate(max_price=Max('book__price')).aggregate(avg_price=Avg('max_price'))
print(ret)
5、每个作者出版的所有书的最高价格以及最高价格的那本书的名称
# 方式1:设置了only_full_group_by
SELECT
t1.name,app01_book.title,ti.mx
FROM
(
SELECT
app01_author.id,
app01_author.name,
MAX(app01_book.price) AS mx
FROM app01_author
INNER JOIN app01_book_author ON app01_author.id = app01_book_author.author_id
INNER JOIN app01_book ON app01_book_author.book_id=app01_book.id
GROUP BY app01_author.id,app01_author.NAME
)AS t1
INNER JOIN app01_book_author ON t1.id=app01_book_author.author_id
INNER JOIN app01_book ON app01_book.id=app01_book_author.book.id
WHERE t1.mx=app01_book.price;
# 方式2:取消了only_full_group_by
SELECT
*
FROM
(SELECT *
FROM app01_author
INNER JOIN app01_book_author ON app01_author.id=app01_book_author.author_id
INNER JOIN app01_book ON app01_book=app01_book_author.book_id
ORDER BY app01_book.price DESC
) AS t1
ORDER BY
app01_author.id,
app01_author.name;
查看mysql服务的sql_mode
select @@sql_mode;
only_full_group_by
大部分公司给自己的mysql设置的是sql_mode:only_full_group_by,也有部分公司没有设置这个模式。这个模式只能影响分组,只要不涉及到分组,这个模式不会影响你的sql语句,如果你写sql时需要分组了,你就需要看看公司的mysql服务端是否设置了only_full_group_by。
only_full_group_by这个模式限制了什么?
分组后,我们select的字段只能是分组的字段或者通过菊虎蛾函数(max、avg、sum等)得到的字段。
如果没有设置这个字段,分组时,他只是那分组的第一条记录以及聚合函数的数据。
ORM加锁
数据库加锁,什么叫锁?锁的种类有什么?
当一个操作某个表或者某条记录时候,有些情况下不允许其他的sql语句操作,这就是加锁。
锁在大方向分类:
1、表级锁
例如:myisam存储引擎支持的就是表级锁。
表级锁就是整个表都锁定了,某个人操作xxx表的一行记录时,整张表都被锁定了,其他的人就得等待这个人操作完毕之后,在依次操作。
2、行级锁
例如:Innodb存储引擎支持的就是行级锁。
某个人操作xxx表的一行记录的时候,只有这一行记录别锁定了,其他人可以操作此表中的其他行,不允许操作此行记录。
锁在小方向分类:
1、共享锁
2、排它锁(互斥锁)
mysql数据库:支持的行级锁,当查询时自动添加的是共享锁,当你做create、update、deleete操作时,mysql自动加行级互斥锁。
ORM事务
什么是事务?
一组sql语句,要么全执行,要么全不执行。 事务的四大特性: 一致性:事务执行前后,数据都是合法的状态,不会违背任何的数据完整性。 原子性:事务包含的所有操作,要么全部成功,要不全部失败回滚。 隔离性:当多个事务并发访问数据时,每个事务之间不能互相干扰 持久性:事务一旦被提交了,那么对数据库中的数据的改变就是永久性的。
-
全局开启事务:
settings.py文件配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'day062', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': 3306, # 'OPTIONS': { # 'init_command': "SET default_storage_engine='INNODB'", # 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", #设置数据库的严格模式 } 'ATOMIC_REQUESTS': True, # 全局开启事务,绑定的是http请求相应的整个过程 # "AUTOCOMMIT":False, #全局取消自动提交,慎用 # 'other': { #配置其它数据库 # 'ENGINE': 'django.db.backends.mysql', # } } }
如果你的一个项目开启了全局事务,Django的整个请求流程:浏览器发送请求,—>url —>views视图函数(默认所有的视图函数) —> render(xx) —> return —> 浏览器只要这个流程中涉及到了sql语句或者orm都给你绑定成事务。
这总全局的事务应用的不多,如果你在全局事务中,某些views函数不想加事务:
from django.db import transaction @transaction.non_atomic_requests def my_view(request): # 给此views函数去掉事务 pass
-
局部开启事务
1、单独给某个views函数开启事务
from django.db import transaction @transaction.atomic def viewfunc(requests): # This conde excutes inside a transaction pass
2、利用上下文管理with语句,给’某块‘镍铜开启事务
from django.db import transaction def viewfunc(requests): # 这部分代码不在事务中,会被Django自动提交 with transaction.atomic(): # 这部分代码会在事务中执行
-