Django ORM中values与annotate函数的实战应用:数据去重与聚合优化

林见深
林见深
发布时间:2026-10-13| 5人浏览过
原创

本文详细解析Django ORM中values和annotate函数的核心用法。通过实际案例演示如何利用values筛选指定字段,结合annotate实现类似SQL的GROUP BY统计功能,从而高效识别并清洗数据库中的重复数据。同时,对比传统遍历计数与annotate聚合查询的性能差异,展示如何在多表关联场景中优化查询效率,避免N+1查询问题,提升Web应用性能。

数据去重需求背景与解决方案概述

项目当前面临一个数据一致性问题:问题表中存储了所有用户提交的问题,主键字段为_id。由于早期数据录入时未对_id字段设置唯一性约束,导致数据库中出现了大量重复使用相同_id编号的问题记录。

核心需求是定位这些_id重复的记录,并在保留每条重复组中第一条数据的前提下,删除其余冗余数据。

在实施具体操作前,需要明确所使用的关键技术手段。

本次解决方案主要依赖Django ORM中的两个关键方法:values和annotate。

简单来说,values方法用于从QuerySet中提取指定字段的值,返回的是包含字典的列表,而非模型实例。

annotate方法则提供了聚合计算能力,其作用类似于SQL语句中的GROUP BY子句,允许对查询结果进行分组统计。

基于上述原理,具体的处理逻辑是:对指定字段进行计数统计,筛选出出现次数大于1的重复_id数据,进而执行数据清洗操作。

利用values和annotate清洗重复数据

首先查看数据库中的原始数据状态。

通过查询获取每条记录中_id字段的具体值。

接下来,对_id字段的出现频次进行统计,以识别重复项。

将查询结果转换为Python列表格式,便于后续处理。

由于只需关注重复数据,因此需要过滤掉那些_id唯一、未重复的记录。

编写一个简单的遍历逻辑来处理筛选后的数据。

遍历过程中,针对每个重复的_id,仅保留其在数据库中创建的第一条记录。

在正式执行删除操作前,导出对应的SQL语句作为备份,确保数据安全。

执行最终的数据清理流程。

具体删除过程涉及对非保留记录的批量删除操作。

操作完成后,返回网站前端验证数据清洗的效果,确认重复数据已移除。

annotate在关联查询中的性能优化

补充说明Django中annotate函数的其他常用场景。

annotate的具体使用方式如下。

在多表关联查询中,例如博客系统包含文章模型和分类模型(分类为文章的外键),若需统计每个分类下的文章数量,常规做法是先获取所有分类对象。

categories = NewsCategory.objects.all()

假设文章模型名为News。

Django会自动为分类模型添加反向关系属性category.news_set,通过调用category.news_set.count()即可获取该分类下的文章数量。

然而,这种方法效率较低,尤其在数据量大时会导致性能瓶颈。若追求更高的查询性能,建议使用annotate进行优化。

下面展示如何使用annotate优化上述查询方法。

categories = NewsCategory.objects.annotate(num_count=Count('news'))

annotate方法会在QuerySet中的每个对象上动态添加一个自定义属性,此处为num_count。

优化后,查询分类下的文章数量变得更为简洁高效。

category.num_count

以下是优化前后的代码对比。

原始代码实现如下:


 def cms_news_category(request):
 categories = NewsCategory.objects.all()
 context = {
  'categories': categories
 }
 return render(request, 'cms/category.html', context=context)
 
 模板category.html中的代码:
 {% for category in categories %}
  <td>{{ category.name }}</td>
  <td>{{ category.news_set.count }}</td>
 {% endfor %}

使用annotate优化后的代码如下:


 def cms_news_category(request):
 categories = NewsCategory.objects.annotate(num_count=Count('news'))
 context = {
  'categories': categories
 }
 return render(request, 'cms/category.html', context=context)
 模板category.html中的代码: 
 {% for category in categories %}
  <td>{{ category.name }}</td>
  <td>{{ category.num_count }}</td>
 {% endfor %}

以上关于Django ORM中values和annotate函数的详解内容,旨在帮助开发者更好地处理数据去重与聚合查询问题,欢迎参考实践。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。