基于Django 4.0获取同部门同标识产品的最新修改记录
Django 4.0 多对多关联下产品数据去重(保留最新修改条目)
问题背景
使用Django 4.0 + Python 3.8,Product模型包含modification_date、designation字段,且与Department模型为多对多关联。需求是查询产品数据时,对相同designation且属于同一Department的产品,仅保留修改时间最新的条目。当前全量查询后手动去重的方式在数据量大时性能极差:
products = Product.objects.all().order_by('designation')
示例数据:
- item_1, 01/01/1970, department_1
- item_2, 01/01/1970, department_2
- item_3, 01/01/1970, department_3
- item_1, 01/02/1970, department_1
期望结果:
- item_1, 01/02/1970, department_1
- item_2, 01/01/1970, department_2
- item_3, 01/01/1970, department_3
解决方案
方法1:Subquery + OuterRef(通用数据库兼容)
将去重逻辑放在数据库层面,通过子查询先获取每个(designation, department)组合的最新修改时间,再筛选对应产品:
from django.db.models import OuterRef, Subquery, Max # 子查询:获取每个(designation, department)对应的最新修改时间 latest_mod_subquery = Product.objects.filter( designation=OuterRef('designation'), departments=OuterRef('departments') # 替换为你的实际多对多关联字段名 ).values('designation', 'departments').annotate( latest_mod=Max('modification_date') ).values('latest_mod') # 主查询:筛选出符合最新修改时间的产品 products = Product.objects.filter( modification_date=Subquery(latest_mod_subquery) ).order_by('designation', '-modification_date')
方法2:PostgreSQL专属DISTINCT ON(高效简洁)
如果项目使用PostgreSQL,可直接利用distinct_on语法,按分组字段排序后取每组第一条:
products = Product.objects.all().order_by( 'designation', 'departments__name', '-modification_date' ).distinct('designation', 'departments__name')
注意:
distinct_on后的字段必须与order_by的前置字段完全匹配,先按分组字段排序,再按修改时间倒序,确保每组第一条为最新条目。
方法3:分组annotate关联查询(简单场景适用)
先分组获取每个组合的最新修改时间,再构造条件筛选产品:
from django.db.models import Max # 获取每个(designation, department)的最新修改时间 latest_groups = Product.objects.values( 'designation', 'departments__name' ).annotate(latest_mod=Max('modification_date')) # 筛选符合条件的产品 products = Product.objects.filter( (Q(designation=item['designation']) & Q(departments__name=item['departments__name']) & Q(modification_date=item['latest_mod'])) for item in latest_groups ).order_by('designation')
注意事项
- 代码中多对多关联字段名(如
departments)需与你的实际模型字段一致,若模型中关联字段为department需对应修改。 - 优先选择方法1或方法2,避免在Python层面处理数据,所有逻辑由数据库完成,性能更优。
内容的提问来源于stack exchange,提问作者agdp
相关产品推荐
相关产品推荐

