Django(10)ORM聚合查询

2023-05-16

文章目录

  • 一、聚合查询—aggregate()
  • 二、分组查询—annotate()
  • 三、F()查询
  • 四、Q()查询

此文章参考菜鸟教程:Django ORM – 多表实例(聚合与分组查询) | 菜鸟教程 (runoob.com)

Django版本:

>>> django.VERSION  
(4, 1, 0, 'final', 0)

PS:基于前几章的进度进行修改

一、聚合查询—aggregate()

  • 聚合查询函数是对一组值执行计算,并且返回单个值
  • Django使用聚合查询之前需要先从django.db.models引入Avg,Max,Min,Count,Sum,注意需要首字母大写
from django.db.models import Avg,Max,Min,Count,Sum

Avg:计算平均值

Max:最大值

Min:最小值

Count:统计出现的次数

Sum:和

  • 聚合查询返回的值的数据类型是字典,而聚合函数aggregate()是QuerySet的一个终止子句,生成的一个汇总值,相当于count()函数。需要注意的是,使用aggregate()后,数据类型就变成了字典类型,不能再使用QuerySet数据类型的一些API了
  • 日期数据类型DateField可以使用MaxMin
  • 返回的字典中,键的名称默认是属性名称+__聚合函数名称,值是计算出来的聚合值,如果要自定义返回字典的键的名称,可以起别名,例如:
aggregate(别名 = 聚合函数名("属性名称"))
  • 实例,计算所有图书的平均价格
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum


def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.aggregate(Avg("price"))
    print(res,type(res))
    return HttpResponse("ok")
  • 访问127.0.0.1:8000/add_book进行测试,观察终端输出,可以看到输出数据类型是字典

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 计算所有图书的数量,价格的最大值和最小值
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum


def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.aggregate(c=Count("id"),max=Max("price"),min=Min("price"))
    print(res,type(res))
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、分组查询—annotate()

  • 分组查询同样也会用到聚合函数,同样先从django.db.models引入Avg,Max,Min,Count,Sum,注意需要首字母大写
from django.db.models import Avg,Max,Min,Count,Sum
  • 返回值:

分组后使用values取值,返回值是QuerySet数据类型里面的一个个字典

如果使用Values_list取值,那么返回值则是QuerySet数据类型里的一个个元组

  • Mysql中的limit就相当于ORM中QuerySet数据类型的切片

  • 注意:

annotate里面存放聚合函数,其中:

  1. values或values_list放在annotate前面:前面的values或values_list声明以什么字段分组,是字典还是元组,而annotate执行分组
  2. values或values_list放在annotate后面:annotate表示直接以当前表的pk(主键)执行分组,后面的values或values_list表示查询哪些字段,==(也就是输出什么字段)==并且要将annotate里面的聚合函数起别名,在values或values_list中写它的别名
  • 准备数据和创建模型
- models.py
# -*- coding: utf-8 -*-
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=32)		
    price = models.DecimalField(max_digits=5,decimal_places=2)	
    pub_date = models.DateField()
    publish = models.ForeignKey("Publish",on_delete=models.CASCADE)  #多对一
    authors = models.ManyToManyField("Author")  #多对多

class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=64)
    email = models.EmailField()

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.SmallIntegerField()
    au_detail = models.OneToOneField("AuthorDetail",on_delete=models.CASCADE)  #一对一

class AuthorDetail(models.Model):
    gender_choices = (
        (0,"女"),
        (1,"男"),
        (2,"保密"),
    )
    gender = models.SmallIntegerField(choices=gender_choices)
    tel = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)
    birthday = models.DateField()

class Emp(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    salary = models.DecimalField(max_digits=8, decimal_places=2)
    dep = models.CharField(max_length=32)
    province = models.CharField(max_length=32)

class Emps(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    salary =     models.DecimalField(max_digits=8, decimal_places=2)
    dep = models.ForeignKey("Dep", on_delete=models.CASCADE)
    province = models.CharField(max_length=32)
    
class Dep(models.Model):
    title = models.CharField(max_length=32)
  • 更新数据表
(test) PS F:\django\app1> python .\manage.py makemigrations app1_model
Migrations for 'app1_model':
  app1_model\migrations\0003_dep_emp_emps_remove_book_authors_remove_book_publish_and_more.py
    - Create model Dep
    - Create model Emp
    - Create model Emps
    - Remove field authors from book
    - Remove field publish from book
    - Delete model Author
    - Delete model AuthorDetail
    - Delete model Book
    - Delete model Publish
(test) PS F:\django\app1> python .\manage.py migrate app1_model
Operations to perform:
  Apply all migrations: app1_model
Running migrations:
  Applying app1_model.0003_dep_emp_emps_remove_book_authors_remove_book_publish_and_more... OK
  • 查看数据库,确认之前的表删除,刚刚新的表创建

在这里插入图片描述

  • 新建查询,写入

在这里插入图片描述

INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('1','令狐冲','24','6000.00','销售部','河南'); 
INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('2','任盈盈','18','8000.00','关公部','广东'); 
INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('3','任我行','56','10000.00','销售部','广东'); 
INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('4','岳灵珊','19','6000.00','关公部','河南'); 
INSERT INTO app1_model_emp (id,name,age,salary,dep,province) VALUES ('5','小龙女','20','8000.00','关公部','河北'); 
INSERT INTO app1_model_dep (id,title) VALUES ('1','销售部'); 
INSERT INTO app1_model_dep (id,title) VALUES ('2','关公部'); 
INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('2','令狐冲','24','8000.00','河南','1'); 
INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('3','任盈盈','18','9000.00','广东','2'); 
INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('4','任我行','57','10000.00','广东','1');
INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('5','岳灵珊','19','6000.00','河南','2');
INSERT INTO app1_model_emps (id,name,age,salary,province,dep_id) VALUES ('6','小龙女','20','8000.00','河北','2');

在这里插入图片描述

  • 查看数据库信息

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 下面统计每一个出版社的最便宜的书的价格
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Publish.objects.values("name").annotate(in_price = Min("book__price"))
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 统计每一本书的作者个数
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.annotate(c = Count("authors__name")).values("title","c")  
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出
    在这里插入图片描述

在这里插入图片描述

  • 统计每一本以Python开头的书籍的作者个数
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.filter(title__startswith="Python").annotate(c = Count("authors__name")).values("title","c")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述
在这里插入图片描述

  • 统计不止一个作者的图书名称
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.annotate(c = Count("authors__name")).filter(c__gt=0).values("title","c")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

  • 根据一本图书作者数量的多少对查询集QuerySet进行降序排序
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.annotate(c = Count("authors__name")).order_by("-c").values("title","c")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

  • 查询各个作者出的书的总价格
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Author.objects.annotate(all=Sum("book__price")).values("name","all")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述
在这里插入图片描述

三、F()查询

  • F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值,之前的过滤器都只是将字段值与某个常量作比较,如果想要对两个字段的值进行比较,就需要用到F()
  • 使用前需要先从django.db.models引入F:
from django.db.models import Avg,Max,Min,Count,Sum,F
  • 语法:F("字段名称")

  • F()动态获取对象字段的值,可以进行运算,Django支持F()对象之间以及F()对象和常数之间的加减乘除和取余的操作,修改操作即update也可以使用F()函数

  • 查询工资大于年龄的人

# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum,F

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    book = models.Emp.objects.filter(salary__gt=F("age")).values("name","age")
    print(book)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

  • 将每一本书的价格提高100元
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum,F

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.update(price=F("price")+100)
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看数据库信息,可以看到成功修改价格
    在这里插入图片描述

在这里插入图片描述

四、Q()查询

  • 使用前需要在django.db.models中引入Q:
from django.db.models import Avg,Max,Min,Count,Sum,F,Q
  • 用法:Q(条件判断),例如
Q(title__startswith="Python")
  • 之前构造的过滤器里的多个条件的关系都是and,如果需要执行更复杂的查询,例如or语句,就可以使用Q()

  • Q对象可以使用&,|,~,即与、或、非等操作符进行组合,优先级从高到低为~ & |,可以混合使用Q对象和关键字参数,Q对象和关键字参数是使用and拼在一起的,即把,看成的关系,但是Q对象必须位于所有关键字参数的前面

  • 查询价格大于350或者名称以Python开头的书籍和名称和价格

# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum,F,Q

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.filter(Q(price__gt=350)|Q(title__startswith="Python")).values("title","price")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

  • 查询以M教程结尾或者不是2011年11月的书籍
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum,F,Q

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.filter(Q(title__endswith="M教程")|~Q(Q(pub_date__year=2011) & Q(pub_date__month=11))).values("title","pub_date")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出

在这里插入图片描述

在这里插入图片描述

  • 查询出版日期是2011年11月的或者2012年10月的,并且名称中包含教程
# -*- coding: utf-8 -*-
from django.shortcuts import render,HttpResponse
from app1_model import models
from django.db.models import Avg,Max,Min,Count,Sum,F,Q

def add_book(request):
    #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10")  
    res = models.Book.objects.filter(Q(pub_date__year=2011) & Q(pub_date__month=11),Q(title__contains="教程")).values("title","pub_date")
    print(res)
    return HttpResponse("ok")
  • 访问测试,查看终端输出
    在这里插入图片描述
    在这里插入图片描述
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django(10)ORM聚合查询 的相关文章

随机推荐

  • AD10 四层板经验(层的性质)

    层的性质 xff1a 内部层有两种 xff1a plane和layer xff0c 他们的区别如下 xff1a plane是所有Layer的其中一个 xff0c Layer是指层 xff0c 例如有常见的信号层Signal Layers 顶
  • Centos7下httpd最新版本安装或者更新至最新版本

    查找Centos上软件库里的httpd版本 yum info httpd yum info httpd 已加载插件 xff1a fastestmirror Loading mirror speeds from cached hostfile
  • 修改git远程仓库地址

    由于git仓库的地址发生了变化 xff0c 需要修改仓库地址才能push 查看本地工程git仓库关联的远程仓库地址 xff1a span class token function git span remote v 删除本地关联的远程仓库地
  • INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法

    在Android模拟器上安装apk的时候出现 xfeff xfeff INSTALL FAILED NO MATCHING ABIS 这个错误提示的解决办法 是由于使用了native libraries 该native libraries
  • IntelliJ IDEA 控制台中文乱码

    1 预热 刚刚接触IntelliJ IDEA几天 xff0c 在易用性方面的确比Eclipse好很多 xff0c 比较智能 xff0c 各种插件 工具都已经集成 xff0c 和Mac OS X类似 开箱即用 但是还是老大难问题 中文乱码 x
  • unable to start the monitor on 4454 ,an other instance is problaly using the same port

    在打开idea studio后 xff0c 再打开android studio xff0c 或者反过来 xff0c 打开项目的时候就会报 xff1a unable to start the monitor on 4454 xff0c an
  • windows中为cmd设置代理

    在CMD环境下设置代理可能不是很常用 xff0c 但是某些情况下还是可能会用到 xff0c 比如有些资源网站被墙了 xff0c 此时你如果想访问这些资源时 xff0c 只能通过代理来访问相应的资源 xff0c 而你需要在CMD环境下下载墙外
  • version `GLIBCXX_3.4.21' not found 解决办法

    在安装cmake3 5 1运行 bootstrap的时候出现如下提示 xff1a gmake cmake 是最新的 span class hljs header usr soft cmake 3 5 1 Bootstrap cmk cmak
  • Oracle死锁查询及处理

    一 数据库死锁的现象 程序在执行的过程中 xff0c 点击确定或保存按钮 xff0c 程序没有响应 xff0c 也没有出现报错 二 死锁的原理 当对于数据库某个表的某一列做更新或删除等操作 xff0c 执行完毕后该条语句不提 交 xff0c
  • Ubuntu 18.04添加中文输入法

    找到设置 xff1a 点击 Manager Installed Languages 出现下图提示 xff1a Keyboard input method system 里面有Ibus XIM fcitx none 三种输入架构 xff0c
  • KEIL问题【打开文件太多造成任何按钮都不可点】【Keil4 编译时出现RL-ARM is not allowed with this license 】【 局部变量仿真显示not in scope】

    SYD8801是一款低功耗高性能蓝牙低功耗SOC xff0c 集成了高性能2 4GHz射频收发机 32位ARM Cortex M0处理器 128kB Flash存储器 以及丰富的数字接口 SYD8801片上集成了Balun无需阻抗匹配网络
  • Django(2)模板、标签

    文章目录 一 使用Django模板修改页面二 Django模板标签 变量 列表 字典 过滤器1 default2 length3 filesizeformat4 date5 truncatechars6 safe if else标签 for
  • Django(3)模型

    文章目录 一 Django 模型 ORM二 数据库配置三 定义模型 xff08 创建数据表 xff09 四 数据库基本操作 插入数据 获取数据 xff08 1 xff09 查询所有的数据行 xff08 2 xff09 where条件查询 x
  • Django(4)表单

    文章目录 一 概述二 GET方法三 POST方法四 Request对象五 QueryDict对象 此文章参考菜鸟教程 xff1a Django 表单 菜鸟教程 runoob com Django版本 xff1a span class tok
  • Django(5)视图

    文章目录 一 视图概述二 请求对象HttpRequest xff08 1 xff09 GET xff08 2 xff09 POST xff08 3 xff09 body xff08 4 xff09 path xff08 5 xff09 me
  • Django(6)路由

    文章目录 一 路由概述二 正则路径中的分组 xff08 1 xff09 正则路径中的无名分组 xff08 2 xff09 正则路径中的有名分组 xff08 3 xff09 路由分发 三 反向解析 xff08 使用reverse xff09
  • Django(7)Admin管理工具

    文章目录 一 概述二 使用管理工具 xff08 1 xff09 激活管理工具 xff08 2 xff09 使用管理工具 xff08 3 xff09 复杂模型 xff08 4 xff09 自定义表单 xff08 5 xff09 内联 xff0
  • Django(8)ORM单表实例

    文章目录 一 Django ORM 单表实例创建新模型 二 数据库操作 xff08 1 xff09 添加数据 xff08 2 xff09 查找数据 filter exclude get order by reverse count firs
  • Django(9)ORM多表实例

    文章目录 一 Django ORM 多表实例创建模型插入数据 二 ORM 插入数据一对多 外键 ForeignKey多对多 xff08 Many ToManyField xff09 xff1a 在第三张表添加数据 三 关联管理器 对象调用1
  • Django(10)ORM聚合查询

    文章目录 一 聚合查询 aggregate 二 分组查询 annotate 三 F 查询四 Q 查询 此文章参考菜鸟教程 xff1a Django ORM 多表实例 xff08 聚合与分组查询 xff09 菜鸟教程 runoob com D