抽象模型自关联多对多字段中%(class)s占位符未正确替换问题
Django抽象模型自关联多对多字段的占位符未替换问题
Django文档推荐使用%(class)s和%(app_label)s占位符设置related_name与related_query_name,但在包含自关联多对多字段的抽象模型中,这些占位符无法被自动替换为预期值。
比如这段代码:
class GeographicalArea(models.Model): successors = models.ManyToManyField( "self", symmetrical=False, blank=True, related_name="%(class)s_predecessors", related_query_name="%(app_label)s_%(class)s_predecessor", help_text="Successors of area if changed.", ) class Meta: abstract = True class Country(GeographicalArea): name = models.CharField( blank=False, unique=True, db_index=True, )
生成的迁移脚本里,related_name仍为%(class)s_predecessors,related_query_name仍为%(app_label)s_%(class)s_predecessor,并没有变成预期的country_predecessors和myapp_country_predecessor(myapp为你的应用名称)。
原因说明
这并非自关联多对多关系不需要占位符,而是Django处理抽象模型自关联字段的特殊逻辑导致的:当字段关联目标写为"self"时,Django会将关联对象绑定到抽象模型本身,而非继承后的具体模型,进而导致占位符无法被后续的具体模型解析替换。
解决方法
把关联目标从"self"改成动态引用格式"%(app_label)s.%(class)s",让Django能正确解析占位符并替换为具体模型的信息:
class GeographicalArea(models.Model): successors = models.ManyToManyField( "%(app_label)s.%(class)s", symmetrical=False, blank=True, related_name="%(class)s_predecessors", related_query_name="%(app_label)s_%(class)s_predecessor", help_text="Successors of area if changed.", ) class Meta: abstract = True class Country(GeographicalArea): name = models.CharField( blank=False, unique=True, db_index=True, )
修改后生成的迁移脚本里,占位符就会被正确替换成具体模型的类名和应用标签。
如果不想修改关联目标格式,也可以在具体模型中重写该字段并手动指定related_name和related_query_name,但这种方式会丧失抽象模型的复用性,不推荐。
内容的提问来源于stack exchange,提问作者arp798
相关产品推荐
相关产品推荐

