如何在Django中根据项目ID获取关联任务的所有阻塞项数据?
解决方案
方法一:基础遍历查询
先获取指定项目的任务集合,再通过外键反向关联(你定义的related_name='task_id_related')获取每个任务对应的阻塞项:
# 获取project_id=1的所有任务 tasks = ProjectTask.objects.filter(project_id=1) # 遍历任务提取阻塞项 for task in tasks: # 通过related_name反向查询该任务的所有TaskBlockers task_blockers = task.task_id_related.all() # 提取blocker字段值组成列表 blocker_content = [item.blocker for item in task_blockers] print(f"任务ID {task.id} 的阻塞项:{blocker_content}")
方法二:预取关联优化查询(避免N+1性能问题)
上面的写法会在遍历每个任务时发起新查询,数据量大时性能低下。用prefetch_related可以一次性预取所有关联的阻塞项,减少数据库请求:
from django.db.models import Prefetch # 预取关联的TaskBlockers,仅加载需要的blocker字段 tasks = ProjectTask.objects.filter(project_id=1).prefetch_related( Prefetch('task_id_related', queryset=TaskBlockers.objects.only('blocker')) ) # 遍历处理,此时不会额外发起数据库查询 for task in tasks: blocker_content = [item.blocker for item in task.task_id_related.all()] print(f"任务ID {task.id} 的阻塞项:{blocker_content}")
方法三:直接从TaskBlockers反向关联查询(最简洁)
如果只需要阻塞项内容,不需要任务的其他信息,可以直接从TaskBlockers模型出发,通过外键链查询:
# 直接获取project_id=1对应的所有blocker值 blocker_list = TaskBlockers.objects.filter( task_id__project_id=1 ).values_list('blocker', flat=True) # 转换为列表查看结果 print(list(blocker_list))
额外优化建议:规范模型字段命名
Django外键字段无需手动加_id后缀,框架会自动生成字段名_id的数据库列。建议修改模型命名提升可读性:
class Projects(models.Model): project_name = models.CharField(max_length=100,null=False) class ProjectTask(models.Model): # 改为project,数据库列仍为project_id project = models.ForeignKey(Projects,on_delete=models.CASCADE,null=False) class TaskBlockers(models.Model): # 改为task,配合更直观的related_name task = models.ForeignKey(ProjectTask,on_delete=models.CASCADE,null=False,related_name='blockers') blocker = models.CharField(max_length=100,null=False)
修改后查询可简化为task.blockers.all(),代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者Akash Rathor
相关产品推荐
相关产品推荐

