聚合查询(聚合函数:最大,最小,和,平均,总个数)
from django.db.models import Avg,Max,Min,Count,Sum
# 1 计算所有图书的平均价格
res = models.Book.objects.aggregate(avg=Avg('price'))
print(res)
# 2 计算总图书数
res = models.Book.objects.aggregate(count=Count('pk'))
print(res)
# 3 计算最低价格的图书
res = models.Book.objects.aggregate(min=Min('price'))
print(res)
# 4 计算最大价格图书
res = models.Book.objects.aggregate(max=Max('price'))
print(res)
# 查询每一个出版社id,以及出书平均价格
res = models.Book.objects.values('publish_id').annotate(avg=Avg('price')).values('publish_id', 'avg')
print(res)
# 查询出版社id大于1的出版社id,以及出书平均价格
res = models.Publish.objects.values('publish_id').filter(publish_id__gt=1).annotate(avg=Avg('book__price')).values('publish_id','avg')
print(res)
res = models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(avg=Avg('price')).values('publish_id','avg')
print(res)
# 查询出版社id大于1的出版社id,以及出书平均价格大于30的出版社和平均价格
res = models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(avg=Avg('price')).filter(avg__gt=30).values('publish_id','avg')
print(res)
# 查询每一个出版社出版的书籍个数
res = models.Publish.objects.values('pk').annotate(count=Count('book__book_id')).values('publish_id', 'count')
print(res)
res = models.Publish.objects.annotate(count=Count('book__book_id')).values('publish_id', 'count')
print(res)
res = models.Book.objects.values('publish_id').annotate(count=Count('pk')).values('publish_id','count')
print(res)
# 查询每个作者的名字,以及出版过书籍的最高价格
res = models.Author.objects.values('pk').annotate(max=Max('book__price')).values('name','max')
print(res)
res = models.Author.objects.annotate(max=Max('book__price')).values('name','max')
print(res)
res = models.Book.objects.values('authors__author_id').annotate(max=Max('price')).values('authors__name','max')
print(res)
# 查询每一个书籍的名称,以及对应的作者个数
res = models.Book.objects.values('pk').annotate(count=Count('authors__pk')).values('name','count')
print(res)
res = models.Book.objects.annotate(count=Count('authors__pk')).values('name','count')
print(res)
res = models.Author.objects.values('book__pk').annotate(count=Count('pk')).values('book__name','count')
print(res)
# 统计不止一个作者的图书
res = models.Book.objects.values('pk').annotate(count=Count('authors__pk')).filter(count__gt=1).values('name', 'count')
print(res)
res = models.Book.objects.annotate(count=Count('authors__pk')).filter(count__gt=1).values('name', 'count')
print(res)
res = models.Author.objects.values('book__pk').annotate(count=Count('pk')).filter(count__gt=1).values('book__name','count')
print(res)
# 统计价格数大于30元,作者的图书
res = models.Book.objects.values('pk').filter(price__gt=30).annotate(count=Count('authors__pk')).values('name','count')
print(res)
res = models.Book.objects.filter(price__gt=30).annotate(count=Count('authors__pk')).values('name', 'count')
print(res)
# 统计价格数大于10元,作者个数大于1的图书
res = models.Book.objects.values('pk').filter(price__gt=10).annotate(count=Count('authors__pk')).filter(count__gt=1).values('name','count')
print(res)
res = models.Book.objects.filter(price__gt=10).annotate(count=Count('authors__pk')).filter(count__gt=1).values('name', 'count')
print(res)
结论
values写在前面表示分组
values写在后面表示取某几个字段
filter写在前面表示where过滤条件
filter写在后面表示having过滤条件
F查询:取出数据库的某个字段的值
# F查询
from django.db.models import F, Q
# 把read_num都加1
res = models.Book.objects.update(read_num=F('read_num') + 1)
print(res)
# 查询评论数大于阅读数的书籍
res = models.Book.objects.filter(comment_num__gt=F('read_num'))
print(res)
# 查询评论数大于阅读数2倍的书籍
res = models.Book.objects.filter(comment_num__gt=F('read_num') * 2)
print(res)
Q查询:制造与或非的条件
# 查询名字叫三国演义或者价格大于100的书
res = models.Book.objects.filter(Q(name='三国演义') | Q(price__gt=100))
print(res)
# 查询名字叫三国演义并且价格大于100的书
res = models.Book.objects.filter(name='三国演义', price__gt=100)
print(res)
res = models.Book.objects.filter(Q(name='三国演义') & Q(price__gt=100))
print(res)
# 查询名字不为三国演义的书
res = models.Book.objects.filter(~Q(name='三国演义'))
print(res)
# Q可以嵌套
res = models.Book.objects.filter(Q(name='三国演义') & Q(price__gt=100) | Q(pk__lt=4))
print(res)
有些sql语句过于复杂繁琐,用orm很难实现,需要借助原生sql解决
from django.db import connection
cursor = connection.cursor()
cursor.execute("select * from book where book_id=%s", [1])
data = cursor.fetchone()
print(data)
data = cursor.fetchall()
print(data)
books = models.Book.objects.raw("select * from book where book_id > 2")
print(type(books)) # RawQuerySet
for book in books:
print(book.name) # {'_state': , 'book_id': 3, 'name': '红楼梦', 'price': Decimal('165.18'), 'publish_time': datetime.datetime(2020, 10, 14, 16, 52, 18, 90262), 'publish_id': 2, 'read_num': 668, 'comment_num': 1238}
惰性查询
如果仅仅只是书写了orm语句,在后面根本没有用到该语句所查询出来的参数,那么orm会自动识别直接不执行
res = models.Book.objects.all().only('name')
print(res[0].name) # 点击only括号内的字段,不会走数据库
print(res[0].price) # 可以查询出来,但是不推荐,点击only括号内没有的字段,会重新走数据库查询
res = models.Book.objects.all().defer('name','price') # 对象除了没有name和price属性之外其他的都有
print(res[0].__dict__) # {'_state': , 'book_id': 1, 'publish_time': datetime.datetime(2020, 10, 14, 16, 51, 16, 86969), 'publish_id': 1, 'read_num': 169, 'comment_num': 133}
总结
only括号内的字段,不会走数据库,only括号内没有的字段,会重新走数据库查询
defer括号内的字段不在查询出来的对象里面,查询该字段需要重新走数据库,而如果查询的是非括号内的字段,则不需要走数据库了
事务(ACID)
1、原子性: 不可分割的最小单位
2、一致性: 跟原子性是相辅相成
3、隔离性: 事务之间互相不干扰
4、持久性: 事务一旦确认永久生效
事务的回滚: rollback
事务的确认: commit
from django.db import transaction
try:
with transaction.atomic():
author_detail = models.AuthorDetail.objects.create(phone=110, gender=2, addr='上海')
author = models.Author.objects.create(name='tommy', age=19, author_detail=author_detail)
...
# 在with代码快内书写的所有orm操作都是属于同一个事务
except Exception as e:
print(e)
print('执行其他操作')
@transaction.atomic
def index(request):
return HttpResponse('ok')
DATABASES = {
'default': {
...
'ATOMIC_REQUEST': True,
}
}
ATOMIC_REQUEST': True,设置为True同一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)