Django多级反向关联导航:从ScanDecision获取关联Project
从ScanDecision获取关联Project的简洁实现
先纠正一个常见误区
你之前写的sd.scan_set.all()是错误的:因为ScanDecision里的scan是ForeignKey正向关联,每个ScanDecision只会对应一个Scan对象,所以直接用sd.scan就能拿到关联的Scan,而不是scan_set.all()(_set是反向关联的用法,比如从Scan获取它的所有ScanDecision,应该用scan.decisions.all(),因为你设置了related_name='decisions')。
方法1:直接链式访问(原生支持)
利用Django ORM的正向关联链式访问,直接通过层级关系获取:
sd = ScanDecision.objects.get(id=1) project = sd.scan.experiment.project
这是最基础的写法,不需要修改模型,直接通过已有的ForeignKey关联逐层访问即可。
方法2:给模型添加属性,实现sd.project的简洁调用
如果想要更符合你预期的sd.project写法,可以给ScanDecision模型添加一个@property装饰器的属性:
class ScanDecision(models.Model): id = models.UUIDField(primary_key=True, default=uuid4, editable=False) scan = models.ForeignKey('Scan', related_name='decisions', on_delete=models.CASCADE) @property def project(self): # 直接返回关联的Project对象 return self.scan.experiment.project
之后就可以直接这样调用:
sd = ScanDecision.objects.get(id=1) project = sd.project
性能优化:避免N+1查询
如果需要批量查询多个ScanDecision并获取它们的Project,一定要用select_related预加载关联对象,避免多次数据库查询:
# 预加载所有层级的关联对象 sd_list = ScanDecision.objects.select_related('scan__experiment__project').all() for sd in sd_list: project = sd.project # 这里不会触发额外的数据库查询
内容的提问来源于stack exchange,提问作者Dave Mackey
相关产品推荐
相关产品推荐

