如何在Django模型继承中修改ManyToMany的through关联模型?
Django模型继承下多对多关联问题解决
问题场景
我遇到了以下模型代码的问题(简化版):
class Node(models.Model): objects = InheritanceManager() node_id = models.AutoField(primary_key=True) links = models.ManyToManyField( "self", through='NodeLinks', blank=True, through_fields=('source', 'target')) class NodeLinks(models.Model): source = models.ForeignKey('Node', related_name='r_source', on_delete=models.CASCADE) target = models.ForeignKey('Node', related_name='r_target', on_delete=models.CASCADE) class Meta: unique_together = (('source', 'target',),) class Tag(Node): label = models.CharField(max_length=200) class TagLinks(NodeLinks): order = models.IntegerField(default=0) TagLinks._meta.get_field('target').related_model = Tag TagLinks._meta.get_field('source').related_model = Tag
执行查询TagLinks.objects.all().values_list('target__label', flat=True)时,本想获取Tag对象的label字段,结果得到的却是没有label字段的NodeLinks对象。目前Tag.links.through关联的是NodeLinks,想知道能否将其修改为TagLinks?
解决方案
1. 在Tag子类中重定义ManyToMany字段
不需要修改父类Node的links字段,直接在Tag类里重新定义links字段,指定through为TagLinks,参数保持和父类一致:
class Tag(Node): label = models.CharField(max_length=200) # 重定义links,关联自定义的中间表TagLinks links = models.ManyToManyField( "self", through='TagLinks', blank=True, through_fields=('source', 'target') )
这样Tag.links.through就会直接指向TagLinks,而非继承自Node的NodeLinks。
2. 规范TagLinks的字段定义
不要用硬改related_model的方式,直接在TagLinks中定义关联Tag模型的外键:
class TagLinks(NodeLinks): # 直接关联Tag而非Node source = models.ForeignKey('Tag', related_name='r_tag_source', on_delete=models.CASCADE) target = models.ForeignKey('Tag', related_name='r_tag_target', on_delete=models.CASCADE) order = models.IntegerField(default=0) class Meta: unique_together = (('source', 'target'),)
这种方式能确保ORM正确识别关联关系,避免后续查询出现字段不存在的问题。
3. 验证查询效果
完成上述修改后,执行TagLinks.objects.all().values_list('target__label', flat=True)就能正确获取到Tag的label字段,同时Tag.links.through也已关联到TagLinks。
内容的提问来源于stack exchange,提问作者Olivier B.
相关产品推荐
相关产品推荐

