Django 聚合分组F与Q查询及choices

宁睿  论坛元老 | 2022-9-23 18:09:36 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1080|帖子 1080|积分 3250

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一、聚合查询

需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg
关键语法:aggregate(聚合结果别名 = 聚合函数(参数))
查询结果:使用聚合函数,从每一个组中获取结果:字典
注意点:
1 聚合函数必须在分组之后才能使用
2 没有分组,即默认整体就是一组
3 查询结果为 普通字典
  1. """
  2.     聚合查询通常情况下都是配合分组一起使用的
  3.     只要是跟数据库相关的模块
  4.       基本上都在 django.db.models 里面
  5.       上述没有那么应该在 django.db里面
  6. """
  7. from django.db.models import Max, Min, Sum, Count, Avg
  8. # 1 所有书的平均价格
  9. res = models.Book.objects.aggregate(Avg('price'))
  10. print(res)
  11. # 2 上述方法一次性使用
  12. res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Count('pk'), Avg('price'))
  13. print(res)
复制代码
 
二、分组查询

1 关键字:annotate
2 默认以当前表 id 分组,并使用聚合函数在组内进行聚合计算,得到结果作为查询结果中组内的属性
  1. from django.db.models import Max, Min, Sum, Count, Avg
  2. # 1 统计每一本书的作者个数
  3. res = models.Book.objects.annotate()  # models后面点什么 就是按什么分组
  4. res1 = models.Book.objects.annotate(author_num = Count('authors')).values('title', 'author_num')
  5. res2 = models.Book.objects.annotate(author_num = Count('authors__nid')).values('title', 'author_num')
  6. print(res, res1, res3)
  7. """
  8. author_num 自己定义的字段 用来存储统计出来的每本书对应的作者个数
  9. """
  10. # 2 统计每个出版社卖的最便宜的书的价格
  11. res = models.Publish.objects.annotate(min_price = Min('book__price')).values('name', 'min_price')
  12. print(res)
  13. # 3 统计不止一个作者的图书
  14. #     先按照图书分组 求每一本书对应的作者个数
  15. #     过滤出不止一个作者的图书
  16. res = models.Book.objects.annotate(author_num = Count('authors')).filter(author_num__gt = 1).values('title', 'author_num')
  17. print(res)
  18. # 4 查询每个作者出的书的总价格
  19. res = models.Author.objects.annotate(sum_price = Sum('book__price')).values('name', 'sum_price')
  20. print(res)
  21. # 5 统计 price大于150元 的书籍的作者个数
  22. res = models.Book.objects.filter(price__gt = 150).annotate(num_authors = Count('authors')).values('title', 'num_authors')
  23. print(res)
复制代码
 
 
三、F与Q查询

 
  1. # F查询
  2. """
  3. 能够帮助你直接获取到表中某个字段对应的数据
  4. """
  5. from django.db.models import F
  6. # 1 将所有书籍的价格提升 10 块
  7. models.Book.objects.update(price = F('price') + 10)
  8. # 2 将 django 书的名称后面加上 ' web' 字
  9. """
  10. 在操作字符类型的数据的时候 F不能够直接做到字符串的拼接
  11. """
  12. from django.db.models.functions import Concat
  13. from django.db.models import Value
  14. models.Book.objects.filter(title = "django").update(title = Concat(F('title'), Value(' web')))
复制代码
 
  1. # Q查询
  2. """
  3. filter括号内多个参数是and关系
  4. """
  5. from django.db.models import Q
  6. # Q包裹逗号分割 还是and关系
  7. res1 = models.Book.objects.filter(Q(price__lt = 300), Q(price__gt = 400))  
  8. print(res1)
  9. # | or关系
  10. res2 = models.Book.objects.filter(Q(pub_date__lt = '2020-01-01') | Q(price__gt = 300))
  11. print(res2)
  12. # ~ not关系
  13. res3 = models.Book.objects.filter( ~ Q(pub_date__lt = '2020-01-01') | Q(price__lt = 200))
  14. print(res3)  # <QuerySet []>
  15. # Q的高阶用法  能够将查询条件的左边也变成字符串的形式
  16. # 提前生成 Q 对象,并使用 append方法 添加条件
  17. q = Q()
  18. q.connector = 'or'
  19. q.children.append(('pub_date__lt', '2020-01-01'))
  20. q.children.append(('price__lt', 200))
  21. res = models.Book.objects.filter(q)  # 默认是and关系
  22. print(res)
复制代码
 
四、特殊参数choices

1 定义字段时,指定参数 choices
2 choices 的值为元组套元组(事先定义好,一般在该表类中定义该字段之前定义)
3 每一个元组存放两个元素,形成一种对应关系
4 往数据库中存值时,该字段的值存为元组第一个元素即可
5 通过 对象.get_字段名_display() 获取对应的元组第二个元素值,当没有对应关系时,返回的是它本身
示例:
  1. # 定义一个 UserTest 表
  2. class UserTest(models.Model):
  3.     name = models.CharField(max_length = 64)
  4.     gender_choices = ((1, '男'),(2, '女'),(3, '其他'))
  5.     gender = models.IntegerField(choices = gender_choices)
  6.    
  7. # 同步迁移到数据库
  8. python manage.py makemigrations
  9. python manage.py migrate
  10. # 在 test.py 配置测试环境
  11. # 录入数据
  12. models.UserTest.objects.create(name = '小微', gender = 1)
  13. models.UserTest.objects.create(name = '小芬', gender = 2)
  14. models.UserTest.objects.create(name = '小桃', gender = 3)
  15. models.UserTest.objects.create(name = '小月', gender = 4)
  16. # 验证choices
  17. for user_obj in models.UserTest.objects.all():
  18.     print(user_obj.gender, end=' ')
  19.     print(user_obj.get_gender_display())
  20. '''
  21. 1 男
  22. 2 女
  23. 3 其他
  24. 4 4
  25. '''
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表