You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 12:35:28