Django 聚合查询

news2024/9/20 6:08:19

文章目录

  • 一、聚合查询
  • 二、使用步骤
    • 1.准备工作
    • 2.具体使用
    • 3.分组查询(annotate)
      • 1.定义
      • 2.使用
      • 3.具体案例
    • 4.F() 查询
      • 1.定义
      • 2.使用
    • 5.Q() 查询
      • 1.定义
      • 2.查询


一、聚合查询

使用聚合查询前要先从 django.db.models 引入 Avg、Max、Min、Count、Sum(首字母大写)
聚合查询返回值的数据类型是字典

聚合查询使用aggregate()对查询集执行聚合操作,它允许我们使用数据库提供的聚合函数(如 COUNT(), AVG(), SUM(), MAX(), MIN() 等)来对查询集中的数据进行汇总计算,aggregate() 方法返回一个字典,字典的键是你指定的聚合函数别名,值是聚合计算的结果

queryset.aggregate(聚合函数)

# 别名使用
queryset.aggregate(别名 = 聚合函数名("属性名称"))
# 例:
result = Book.objects.aggregate(average_price=Avg('price'), total_books=Count('id'))
# 结果示例: {'average_price': 100.25, 'total_books': 150}

二、使用步骤

1.准备工作

还是之前那个fa的项目目录,在views.py内引入

# 导入聚合函数
from django.db.models import Avg,Max,Min,Count,Sum

在models.py里面,定义一个Book模型

class Book(models.Model):
    title = models.CharField(max_length=255)  # 书名
    author = models.CharField(max_length=255)  # 作者
    price = models.DecimalField(max_digits=10, decimal_places=2)  # 价格
    rating = models.FloatField()  # 评分
    published_date = models.DateField()  # 出版日期
    pages = models.IntegerField()  # 页数

    def __str__(self):
        return self.title

在数据库生成book表,执行下列命令

python manage.py makemigrations
python manage.py migrate

这个时候我们就有一张book的表了,我们自己手动塞入一些数据(这里就不做新增了),然后在下一步实现聚合函数的使用
随意添加的数据
在这里插入图片描述

2.具体使用

定义一个方法去使用聚合函数,我们在views.py里面添加一个方法

def getBookSomeInfo(request):
    # 计算书的平均价格
    average_price = models.Book.objects.aggregate(avg_price = Avg('price'))
    # 如果不加别名结果为: {'price__avg': 100.25}

    # 获取书的最高价格
    max_price = models.Book.objects.aggregate(Max('price'))

    # 获取书的最低价格
    min_price = models.Book.objects.aggregate(min_price = Min('price'))

    # 统计书的总数量
    # book_count = models.Book.objects.aggregate(Count('id'))
    book_count = models.Book.objects.aggregate(book_count = Count('id'))
    # 其实也可以使用 len(models.Book.objects.all()) / models.Book.objects.count()

    # 计算所有书的总价格
    total_price = models.Book.objects.aggregate(total_price = Sum('price'))

    return HttpResponse(f"平均价格: {average_price}, 最高价格: {max_price}, 最低价格: {min_price}, 总数量: {book_count}, 总价格: {total_price}")

在路由urls.py里面添加

    path('getBookSomeInfo', views.getBookSomeInfo, name='getBookSomeInfo'),

访问链接http://127.0.0.1:8082/article/getBookSomeInfo
在这里插入图片描述

3.分组查询(annotate)

1.定义

annotate() 是 Django ORM 提供的一个方法,用于在查询集中为每个对象添加计算值。与 aggregate() 方法不同,annotate() 是逐个对象进行计算,而 aggregate() 是对整个查询集进行计算,并返回一个汇总结果

2.使用

使用前要先从 django.db.models 引入聚合函数,annotate() 方法接受一个或多个聚合函数作为参数,这些聚合函数会被应用到查询集中,并将结果作为额外字段添加到每个对象上

queryset.annotate(聚合函数)

3.具体案例

我们先修改一下刚刚定义的Book模型,同时增加一个作者User模型

class User(models.Model):
    name = models.CharField(max_length=255)  # 作者名称

    def __str__(self):
        return self.name


class Book(models.Model):
    title = models.CharField(max_length=255)  # 书名
    # author = models.CharField(max_length=255)  # 作者
    user = models.ForeignKey(User, related_name='books', null=True, on_delete=models.CASCADE)  # 作者
    price = models.DecimalField(max_digits=10, decimal_places=2)  # 价格
    rating = models.FloatField()  # 评分
    published_date = models.DateField()  # 出版日期
    pages = models.IntegerField()  # 页数

    def __str__(self):
        return self.title

执行命令生成数据表,user表和book表都先手动写入数据,不通过程序写入数据
views.py增加方法

def getBookFormUser(request):
    # 计算每个作者的书籍数量

    # 这里的 'books' 是 models.User 类中定义的外键名称,如果外键名称不是 'books' 则需要修改
    users_with_book_count = models.User.objects.annotate(book_count = Count('books'))

    users_with_book_count_str = ''
    # 输出每个作者的书籍数量
    for user in users_with_book_count:
        users_with_book_count_str += f"{user.name} has {user.book_count} books.\n"

    # 计算每个作者的书籍平均价格
    # books__price 代表 books 外键的 price 字段
    users_with_avg_price = models.User.objects.annotate(avg_price = Avg('books__price'))

    users_with_avg_price_str = ''
    # 输出每个作者的书籍平均价格
    for user in users_with_avg_price:
        users_with_avg_price_str += f"{user.name} has an average book price of {user.avg_price}.\n"

    # 计算每个作者的书籍总价格和最高评分
    users_with_totals = models.User.objects.annotate(total_price = Sum('books__price'), highest_rating = Max('books__rating'))

    users_with_totals_str = ''

    # 输出每个作者的书籍总价格和最高评分
    for user in users_with_totals:
        users_with_totals_str += f"{user.name} has a total book price of {user.total_price} and the highest rating is {user.highest_rating}.\n"

    # 返回带有换行符的 HTML 响应,确保编码为UTF-8
    return HttpResponse(
        f"每个作者的书籍数量: <br>{users_with_book_count_str}<br>"
        f"每个作者的书籍平均价格: <br>{users_with_avg_price_str}<br>"
        f"每个作者的书籍总价格和最高评分: <br>{users_with_totals_str}",
        content_type="text/html; charset=utf-8"
    )

增加路由

path('getBookFormUser', views.getBookFormUser, name='getBookFormUser'),

访问链接http://127.0.0.1:8000/article/getBookFormUser
在这里插入图片描述

4.F() 查询

1.定义

F() 表达式用于在数据库中直接引用字段的值,而不是将值从数据库取出后再进行计算。它允许你在数据库层面进行原子性的计算操作,从而避免出现竞争条件或数据不同步的问题,常用于以下场景:

对字段值进行加减、乘除等数学运算。
比较同一个模型中不同字段的值。
更新字段时直接使用该字段的当前值。

2.使用

要使用 F() 表达式,你需要从 django.db.models 中导入 F 类

from django.db.models import F
  1. 字段值的更新(如:增加浏览数)
  2. 先更新一下Book模型
class Book(models.Model):
    title = models.CharField(max_length=255)  # 书名
    # author = models.CharField(max_length=255)  # 作者
    user = models.ForeignKey(User, related_name='books', null=True, on_delete=models.CASCADE)  # 作者
    price = models.DecimalField(max_digits=10, decimal_places=2)  # 价格
    rating = models.FloatField()  # 评分
    published_date = models.DateField()  # 出版日期
    pages = models.IntegerField()  # 页数
    views = models.IntegerField(default=0)  # 浏览量

    def __str__(self):
        return self.title
  1. 定义方法和路由
def addViews(request):
    # 增加阅读量
    article_id = 1
    models.Book.objects.filter(id=article_id).update(views=F('views') + 1)
    return HttpResponse('Views added successfully')

path('addViews', views.addViews, name='addViews'),
  1. 访问链接http://127.0.0.1:8000/article/addViews
    在这里插入图片描述
  2. 一些其他场景
    定义方法和路由
def someOtherInfo(request):
    # 比较同一个模型的两个字段的值
    # 获取 price 大于 discount_price 的商品,这个查询会返回所有 price 大于 discount_price 的 Product 实例
    # 注意:F() 函数用于引用其他字段的值,不能用于直接比较两个字段的值,price和views都是字段名
    book_gt_discount = models.Book.objects.filter(price__gt=F('views'))
    book_gt_discount_str = ''
    for item in book_gt_discount:
        book_gt_discount_str += f"Book {item.id} has a price of {item.price} and views of {item.views}\n"
    
    # 多字段运算
    # 获取所有books的总价格和评分的乘积
    # 使用 F() 表达式在 annotate 中
    books = models.Book.objects.annotate(total_price=F('price') * F('views'))

    str_books = ''
    for item in books:
        str_books += f"Book {item.id} has total price {item.total_price}\n"
    
    # 查询时对字段进行运算
    # 获取book的价格大于其views加500的书籍
    high_books = models.Book.objects.filter(price__gt=F('views') + 500.00)
    high_books_str = ''
    for item in high_books:
        high_books_str += f"Book {item.id} has a price of {item.price}\n"

    return HttpResponse(
        f"book_gt_discount: <br>{book_gt_discount_str}<br>"
        f"str_books: <br>{str_books}<br>"
        f"high_books_str: <br>{high_books_str}",
        content_type="text/html; charset=utf-8"
    )

path('someOtherInfo', views.someOtherInfo, name='someOtherInfo'),

访问链接http://127.0.0.1:8000/article/someOtherInfo
在这里插入图片描述

5.Q() 查询

1.定义

Q() 对象来自 django.db.models,用于创建复杂的查询条件。你可以使用它来结合多个条件,执行与(AND)或或(OR)操作,甚至是非(NOT)操作,尤其是在需要执行“OR”操作或者需要多个条件组合时非常有用。Q() 对象使得构建复杂的查询变得更加灵活和强大,
使用前还是先导入

from django.db.models import Q

2.查询

定义方法和路由

def searchByq(request):
    # 按价格和阅读量查询书籍
    # 注意:Q() 函数用于构建复杂的查询条件,可以与其他条件组合使用
    # 这里的 Q() 函数与 price__gt 条件组合使用,表示价格大于 500.00
    # 与 views__gt 条件组合使用,表示阅读量大于 1
    books_and = models.Book.objects.filter(Q(price__gt=500.00) & Q(views__gt=1))
    books_and_str = ''
    for item in books_and:
        books_and_str += f"Book {item.id} has a price of {item.price} and views of {item.views}\n"
    
    # 按价格或阅读量查询书籍
    # 这里的 Q() 函数与 price__gt 条件组合使用,表示价格大于 500.00
    # 与 views__gt 条件组合使用,表示阅读量大于 1
    books_or = models.Book.objects.filter(Q(price__gt=500.00) | Q(views__gt=1))
    books_or_str = ''
    for item in books_or:
        books_or_str += f"Book {item.id} has a price of {item.price} and views of {item.views}\n"
    
    # 按价格范围查询书籍
    # 这里的 Q() 函数与 price__range 条件组合使用,表示价格在 500.00 到 1000.00 之间
    books_range = models.Book.objects.filter(Q(price__range=(500.00, 1000.00)))
    books_range_str = ''
    for item in books_range:
        books_range_str += f"Book {item.id} has a price of {item.price}\n"
    
    # not 查询 这里使用的 ~Q() 函数表示价格不大于 500.00
    books_not = models.Book.objects.filter(~Q(price__gt=500.00))
    books_not_str = ''
    for item in books_not:
        books_not_str += f"Book {item.id} has a price of {item.price}\n"
    return HttpResponse(
        f"books_and_str: <br>{books_and_str}<br>"
        f"books_or_str: <br>{books_or_str}<br>"
        f"books_range_str: <br>{books_range_str}"
        f"books_not_str: <br>{books_not_str}",
        content_type="text/html; charset=utf-8"
    )

    path('searchByq', views.searchByq, name='searchByq'),

访问链接http://127.0.0.1:8000/article/searchByq
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2148187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VS code EXPLORER 中不显示指定文件及文件夹设置(如.pyc, __pycache__, .vscode 文件)

VS code EXPLORER 中不显示指定文件及文件夹设置 引言正文方法1打开方式1打开方式2 方法2 引言 VS code 号称地表最强轻量级编译器&#xff0c;其最大的优势在于用户可以根据自己的需求下载适合自己的 extension。从而定制个性化的编译器。然而&#xff0c;本人今天遇到了一个…

如何调用API接口:一份简明指南

在软件开发中&#xff0c;调用API接口是一项基本而重要的技能。API&#xff08;应用程序编程接口&#xff09;允许不同程序之间进行交互&#xff0c;使得数据和功能可以跨应用程序共享。本文将为你提供一份简明的指南&#xff0c;帮助你理解如何调用API接口。 什么是API接口&am…

Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap

在Android开发中&#xff0c;内存管理是一个非常重要的话题。为了更好地管理内存&#xff0c;Java和Android提供了多种引用类型&#xff0c;包括Weak Reference、Soft Reference、Phantom Reference以及WeakHashMap。这些引用类型在不同的场景下可以帮助我们更有效地管理内存&a…

(笔记)mac笔记本调节键盘速率

我在使用neovim的时候&#xff0c;发现按下hjkl或者shift[]来进行移动的时候 开始延迟大概几百毫秒的时间才开始移动 所以我上网找了下方法 发现修改这了可以改变速率 我就直接拉到了fast 芜湖 起飞 local opt vim.opt local o vim.o local g vim.go.timeoutlen 100 o…

论文速递!时序预测!DCSDNet:双卷积季节性分解网络,应用于天然气消费预测过程

本期推文将介绍一种新的时序预测方法:双卷积季节性分解网络&#xff08;Dual Convolution withSeasonal Decomposition Network, DCSDNet&#xff09;在天然气消费预测的应用&#xff0c;这项研究发表于《Applied Energy》期刊。 针对天然气消费的多重季节性和非规律性&#x…

汽车焊机数据通信:Profinet转Canopen网关的神奇连接

在汽车制造领域&#xff0c;汽车焊机的高效、稳定运行对于整车质量至关重要。而Profinet转Canopen网关在汽车焊机的数据通信中发挥着关键作用。 Profinet是一种广泛应用于工业自动化领域的通信协议&#xff0c;具有高速、实时、可靠等特点。Canopen则在汽车电子等领域有着广泛…

软件渗透测试流程有哪些?专业软件测评公司简析渗透测试的好处

软件渗透测试是进行软件安全测评的重要环节&#xff0c;旨在通过模拟攻击手段发现软件系统的脆弱性。这种安全测试方法能够帮助开发人员和系统管理员发现并修复潜在的安全漏洞&#xff0c;以确保软件系统的安全性和完整性。软件渗透测试是一项高度技术性的任务&#xff0c;需要…

口哨声、歌声、boing声和biotwang声:用AI识别鲸鱼叫声

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

算法打卡 Day41(动态规划)-理论基础 + 斐波那契数 + 爬楼梯 + 使用最小花费爬楼梯

文章目录 理论基础Leetcode 509-斐波那契数题目描述解题思路 Leetcode 70-爬楼梯题目描述解题思路 Leetcode 746-用最小花费爬楼梯题目描述解题思路 理论基础 动态规划&#xff0c;简称 DP&#xff0c;其中的每一个状态一定是由上一个状态推导出来的&#xff0c;而贪心算法没有…

Mastering Qt 番外 —— 添加源码调试

笔者最近正在尝试深入的学习Qt框架&#xff0c;经常需要明确我经常使用的类底下发生了什么&#xff0c;因此笔者决定仔细研究一下如何进行源码级别的调试 此篇文章将会介绍如何使用Qt Creator这个IDE进行调试。最终效果如下 EasyWay 笔者采用的是这个最简单明了的方式&#xff…

回归预测|基于鹈鹕优化径向基神经网络的数据回归预测Matlab程序POA-RBF 多特征输入单输出 含基础RBF

回归预测|基于鹈鹕优化径向基神经网络的数据回归预测Matlab程序POA-RBF 多特征输入单输出 含基础RBF 文章目录 一、基本原理1. **饥饿游戏搜索优化算法&#xff08;POA&#xff09;简介**2. **径向基神经网络&#xff08;RBF&#xff09;简介**3. **POA-RBF回归预测流程**1. **…

重修设计模式-设计原则

重修设计模式-设计原则 设计原则 设计原则是软件编码时所遵循的规则&#xff0c;旨在帮助开发者创建出既满足功能需求又易于维护、可扩展且美观的设计&#xff0c;理解设计原则可以提升代码质量、减少错误以及促进团队协作&#xff0c;但对设计原则的理解要灵活&#xff0c;不…

前端vue-父传子

父传子的话是在components中创建一个子组件MyTest.vue&#xff0c;并且在父组件中先导入(import MyTest from "./components/MyTest")&#xff0c;再注册&#xff08;在expo二default中写上 compnents:{MyTest}&#xff09;&#xff0c;再使用标签&#xff08;<My…

深度学习后门攻击分析与实现(一)

在计算机安全中&#xff0c;后门攻击是一种恶意软件攻击方式,攻击者通过在系统、应用程序或设备中植入未经授权的访问点,从而绕过正常的身份验证机制,获得对系统的隐蔽访问权限。这种"后门"允许攻击者在不被检测的情况下进入系统,执行各种恶意活动。 后门可以分为几种…

开源项目 GAN 漫画风格化 UGATIT

开源项目&#xff1a;DataBall / UGATIT GitCode * 数据集 * [该项目制作的训练集的数据集下载地址(百度网盘 Password: gxl1 )](https://pan.baidu.com/s/1683TRcv3r3o7jSitq3VyYA) * 预训练模型 * [预训练模型下载地址(百度网盘 Password: khbg )](https://pan.ba…

安卓实现导入Excel文件

使用简化版的jar包 api files(libs/poi-3.12-android-a.jar) api files(libs/poi-ooxml-schemas-3.12-a.jar) 导入遇到了两个兼容问题 1.build.gradle文件里面 android { 要添加 packagingOptions {exclude META-INF/INDEX.LIST } 2.加载大文件要在清单文件里面加androi…

2023年全国研究生数学建模竞赛华为杯B题DFT类矩阵的整数分解逼近求解全过程文档及程序

2023年全国研究生数学建模竞赛华为杯 B题 DFT类矩阵的整数分解逼近 原题再现&#xff1a; 一、问题背景   离散傅里叶变换&#xff08;Discrete Fourier Transform&#xff0c;DFT&#xff09;作为一种基本工具广泛应用于工程、科学以及数学领域。例如&#xff0c;通信信号…

YOLO交通目标识别数据集(红绿灯-汽车-自行车-卡车等)

YOLO交通目标识别 数据集 模型 ui界面 ✓图片数量15000&#xff0c;xml和txt标签都有&#xff1b; ✓class&#xff1a;biker&#xff0c;car&#xff0c;pedestrian&#xff0c;trafficLight&#xff0c;trafficLight-Green&#xff0c;trafficLight-GreenLeft&#xff0c; t…

java se 快速入门

文章目录 java se 快速入门Java 简介Java的优点jdk 和 jre安装jdk配置环境变量Java 语法快速入门程序入口文件名类规范 基本语法注释变量和常量输入输出条件语句循环语句 基本数据类型Java字符串常用方法字符串拼接java字节数组和字符串相互转化java字符数组和字符串相互转换ja…

美畅物联丨技术前沿探索:H.265编码与畅联云平台JS播放器的融合应用

一、H.265 编码&#xff1a;视频压缩技术的重大变革 H.265&#xff0c;即被熟知为高效视频编码&#xff08;HEVC&#xff0c;High Efficiency Video Coding&#xff09;&#xff0c;由国际电信联盟电信标准化部门视频编码专家组&#xff08;ITU-T VCEG&#xff09;与国际标准化…