聚合查询
在sql语句中,我们知道聚合语句,比如查询最大值,最小值,平均值等等。在ORM中,使用aggregate()来进行聚合查询,首先需要导入
from django.db.models import Max, Min, Avg, Sum, Count
查询价格最大是多少
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.aggregate(Max('price')) print(ret) ret = models.Book.objects.all().aggregate(Max('price')) print(ret)
结果:
{'price__max': 66} {'price__max': 66}
结果是一个字典格式,key为“字段_聚合名”,如果你看它不爽,你也可以自定义
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.aggregate(最大值=Max('price'),最小值=Min('price')) print(ret)
结果:
{'最大值': 66, '最小值': 22}
注意:如果你查询了多个,有些聚合你自己定义了名称,有些你没有定义名称,则没有定义名称的要放在前面(位置参数不能在关键字参数后面)
分组查询
先来看一下数据表关系
查询出每本书的作者
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.annotate(num=Count('author')) print(ret)
结果是QuerySet
<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>]>
使用.values()获取所有
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.annotate(num=Count('author')).values() for i in ret: print(i)
结果:
{'id': 1, 'title': 'linux', 'price': 22, 'publisher_id': 2, 'num': 1} {'id': 2, 'title': 'python入门到放弃', 'price': 55, 'publisher_id': 3, 'num': 0} {'id': 3, 'title': 'java直接放弃', 'price': 22, 'publisher_id': 3, 'num': 1} {'id': 4, 'title': 'go精通', 'price': 54, 'publisher_id': 1, 'num': 2} {'id': 5, 'title': '一小时精通Django', 'price': 66, 'publisher_id': 3, 'num': 1}
可以在value里指定参数获取想要的字段
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.annotate(num=Count('author')).values('title','num') for i in ret: print(i)
结果:
num对应的值就是这本书作者的个数
{'title': 'linux', 'num': 1} {'title': 'python入门到放弃', 'num': 0} {'title': 'java直接放弃', 'num': 1} {'title': 'go精通', 'num': 2} {'title': '一小时精通Django', 'num': 1}
统计每个出版社最便宜的书的价格
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.values('publisher_id').annotate(min_num=Min('price')) for i in ret: print(i)
结果:
{'publisher_id': 1, 'min_num': 54} {'publisher_id': 2, 'min_num': 22} {'publisher_id': 3, 'min_num': 22}
因为不分组的结果
from django.db.models import Max, Min, Avg, Sum, Count ret = models.Book.objects.values('publisher_id') for i in ret: print(i)
结果:
{'publisher_id': 1} {'publisher_id': 2} {'publisher_id': 3} {'publisher_id': 3} {'publisher_id': 3}
统计不止一个作者的图书
ret = models.Book.objects.annotate(num=Count('author')).filter(num__gt=1).values() for i in ret: print(i)
结果:
{'id': 4, 'title': 'go精通', 'price': 54, 'publisher_id': 1, 'num': 2}
查询各个作者出的书的总价格
F查询
在之前的查询中,我们都是拿某个字段对一个固定的值做比较,如果想用字段和字段做比较,就要用到F查询了,先来看下数据表里的数据
需求,查出所有num大于money的
from django.db.models import F ret = models.Book.objects.filter(num__gt=F('money')).values() for i in ret: print(i)
结果:
{'id': 1, 'title': 'linux', 'price': 22, 'publisher_id': 2, 'money': 23, 'num': 65} {'id': 4, 'title': 'go精通', 'price': 54, 'publisher_id': 1, 'money': 33, 'num': 88} {'id': 5, 'title': '一小时精通Django', 'price': 66, 'publisher_id': 3, 'money': 44, 'num': 99}
需求:给每个num的值*2
之前的都是对某一条数据更新的,如
ret = models.Book.objects.get(id=2) ret.num=24 ret.save()
上面的这种写法要进行save(),而且要写更新的具体数值
使用update更新
ret = models.Book.objects.filter(id=2).update(num=50)
update就不需要save
ret = models.Book.objects.update(num=50) # 对所有的数据更新
这两种写法都满足不了我们的需求,我们用F来实现,下面两种结果是一样的
from django.db.models import F ret = models.Book.objects.update(num=F('num')*2) ret = models.Book.objects.all().update(num=F('num')*2)
需求:在所有书名后面加上(测试)
ret = models.Book.objects.update(title=Concat(F("title"), Value("("), Value("测试"), Value(")")))
不需要()
ret = models.Book.objects.update(title=Concat(F("title"), Value("测试")))
Q查询
之前我们所有进行的查询都是and关系的,如果要使用or关系的查询,就要用Q查询了。继续看数据表数据
需求:查询id小于3并且大于等于6的
from django.db.models import Q ret = models.Author.objects.filter(Q(id__lt=3) | Q(id__gte=6)).values() for i in ret: print(i)
结果:管道符( | )表示或的关系
{'id': 1, 'name': '孙悟空'} {'id': 2, 'name': '猪八戒'} {'id': 6, 'name': '蜘蛛精'} {'id': 7, 'name': '女儿国'} {'id': 8, 'name': '紫霞仙子'}
&表示并且的关系
from django.db.models import Q ret = models.Author.objects.filter(Q(id__lt=7) & Q(id__gte=6)).values() for i in ret: print(i)
结果:
{'id': 6, 'name': '蜘蛛精'}
~表示取反
from django.db.models import Q ret = models.Author.objects.filter(~Q(id__lt=7) & Q(id__gte=6)).values() for i in ret: print(i)
结果:
{'id': 7, 'name': '女儿国'} {'id': 8, 'name': '紫霞仙子'}
事务
事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。
针对上面的描述可以看出,事务的提出主要是为了解决并发情况下保持数据一致性的问题。
事务具有以下4个基本特征。
- Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。
- Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。
- Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
- Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_project.settings") import django django.setup() from appTest01 import models try: from django.db import transaction with transaction.atomic(): 这里写要执行的ORM语句 except Exception as e: print(str(e))