Django聚合查询、分组查询、F和Q查询、原生sql、orm语句的特点、only与defer及在django中如何开启事务

文章目录

      • 1、聚合查询
      • 2、分组查询
      • 3、F和Q查询
        • 3.1、F查询
        • 3.2、Q查询
      • 4、原生sql
        • 4.1、方式一(使用频率少)
        • 4.2、方式二(使用频率高)
      • 5、orm语句的特点
      • 6、only与defer
        • 6.1、only
        • 6.2、defer
      • 7、django中如何开启事务(请求,装饰器,局部)
        • 7.1、什么是事务
        • 7.2、事物的三个粒度
          • 7.2.1、局部使用
          • 7.2.2、视图函数装饰器(这一个视图函数都在一个事物中)
          • 7.2.3、整个http请求在一个事务中,需要在setting.py中配置

1、聚合查询

聚合查询(聚合函数:最大,最小,和,平均,总个数)

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)

2、分组查询

# 查询每一个出版社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过滤条件

3、F和Q查询

3.1、F查询

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)
3.2、Q查询

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)

4、原生sql

有些sql语句过于复杂繁琐,用orm很难实现,需要借助原生sql解决

4.1、方式一(使用频率少)
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)
4.2、方式二(使用频率高)
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}

5、orm语句的特点

惰性查询
如果仅仅只是书写了orm语句,在后面根本没有用到该语句所查询出来的参数,那么orm会自动识别直接不执行

6、only与defer

6.1、only
res = models.Book.objects.all().only('name')
print(res[0].name)  # 点击only括号内的字段,不会走数据库
print(res[0].price)  # 可以查询出来,但是不推荐,点击only括号内没有的字段,会重新走数据库查询
6.2、defer
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括号内的字段不在查询出来的对象里面,查询该字段需要重新走数据库,而如果查询的是非括号内的字段,则不需要走数据库了

7、django中如何开启事务(请求,装饰器,局部)

7.1、什么是事务
事务(ACID)
1、原子性: 不可分割的最小单位
2、一致性: 跟原子性是相辅相成
3、隔离性: 事务之间互相不干扰
4、持久性: 事务一旦确认永久生效
	
事务的回滚: rollback
事务的确认: commit
7.2、事物的三个粒度
7.2.1、局部使用
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('执行其他操作')
7.2.2、视图函数装饰器(这一个视图函数都在一个事物中)
@transaction.atomic
def index(request):
	return HttpResponse('ok')
7.2.3、整个http请求在一个事务中,需要在setting.py中配置
DATABASES = {
    'default': {
        ...
        'ATOMIC_REQUEST': True,
    }
}

ATOMIC_REQUEST': True,设置为True同一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)

你可能感兴趣的:(python,orm,django)