Django多对多关联表:查询无分配或最新分配为Drop的任务
解决多对多关联下的任务查询需求
嘿,作为新手程序员能想到用多对多关联建模已经很棒了!针对你要查询的两个条件,我给你整理了两种可行的Django ORM查询方案,都能高效处理你说的数百任务、数千分配记录的场景:
核心需求拆解
你需要的任务分为两类:
- 完全没有任何分配记录的任务
- 有分配记录,但最新一条分配类型是
Drop(对应你模型里的DROP常量)的任务
方案一:子查询组合(推荐,性能更优)
这种方式通过子查询精准定位每个任务的最新分配记录,再筛选符合条件的任务:
from django.db.models import Subquery, OuterRef, Max, Q # 假设你的DROP常量值是'Drop',如果不是请替换成实际定义的内容 DROP = 'Drop' # 第一步:子查询获取每个任务的最新分配更新时间 latest_assignment_subquery = Assignments.objects.filter( # 通过related_name关联到Tasks,你的模型里related_name是"assignments" assignments=OuterRef('pk') ).values('assignments').annotate( latest_date=Max('assignment_update_date') ).values('latest_date') # 第二步:子查询筛选出最新分配类型为Drop的任务ID drop_task_ids = Assignments.objects.filter( assignments=OuterRef('pk'), assignment_update_date=Subquery(latest_assignment_subquery), assignment_type=DROP ).values('assignments') # 第三步:组合两个条件查询最终任务 target_tasks = Tasks.objects.filter( # 条件1:无任何分配记录 Q(task_assignment__isnull=True) | # 条件2:最新分配是Drop的任务 Q(pk__in=Subquery(drop_task_ids)) ).distinct()
代码解释
- 第一个子查询
latest_assignment_subquery:给每个任务计算出它所有分配记录里的最新更新时间 - 第二个子查询
drop_task_ids:找到那些最新更新时间对应的分配记录类型是Drop的任务ID - 最后用
Q()组合两个条件,distinct()用来避免多对多关联导致的重复任务记录
方案二:Annotate标注+筛选
这种方式通过给每个任务标注最新分配时间,再进行条件判断:
from django.db.models import Max, Q, F DROP = 'Drop' # 先给每个任务标注最新的分配更新时间 tasks_with_latest_date = Tasks.objects.annotate( latest_assignment_date=Max('task_assignment__assignment_update_date') ) # 筛选符合条件的任务 target_tasks = tasks_with_latest_date.filter( # 条件1:无分配记录(标注的最新时间为null) Q(latest_assignment_date__isnull=True) | # 条件2:存在一条分配记录,其时间等于最新时间且类型是Drop Q( task_assignment__assignment_update_date=F('latest_assignment_date'), task_assignment__assignment_type=DROP ) ).distinct()
注意事项
- 确保你模型里的
DROP常量值和查询中使用的一致,比如如果你的Type里DROP对应的是'Dropped From',那查询里要改成这个字符串 - 两种方案都用了
distinct(),因为多对多关联查询时,同一任务可能会被匹配多次,去重后结果更准确 - 你可以先手动找几个测试任务(比如无分配的、最新是Drop的),运行查询后验证结果是否符合预期
内容的提问来源于stack exchange,提问作者revisorx
相关产品推荐
相关产品推荐

