我正在将项目从django 1.8升级到1.10,看起来django已经改进了对外键和模型继承之间最终名称冲突的检查。 这显然是一件好事,但我需要升级的项目是一个很大的项目,重命名一个模型将是一个地狱。
让我解释一下这个问题:我有一个名为Parent
的基类和许多链接在一起的孩子,如下所示:
class Parent(models.Model):
title = models.CharField(max_length=10)
class ChildA(Parent):
description = models.TextField()
class ChildB(Parent):
description = models.TextField()
childa = models.ForeignKey(ChildA)
这里的冲突是childb
对象有2" childa"属性:
parent
属性)。这里有两个明显的解决方案:
ChildB.childa
重命名为ChildB.somethingelse
ChildA
模型重命名为其他内容。 这两种解决方案都花费了很多,并且可能会引入新的错误。 所以我想知道:是否可以重命名继承对象的反向相关名称?
例如:
p = Parent.objects.get(pk=1)
print p.childa_child # Hit the ChildA instance
我不知道我是否足够清楚,但我会及时更新这个问题。
====编辑====
为了更简洁,如果我有2个模型class Parent(models.Model)
和class Child(Parent)
,则会创建动态属性parent.child
。
是否可以在不触及班级名称的情况下编辑此属性名称?
答案 0 :(得分:4)
多表继承在基本模型和子类之间创建隐式OneToOneField
字段。
Django允许您通过显式设置一对一字段来修改此关系。
class Parent(models.Model):
title = models.CharField(max_length=10)
class ChildA(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True)
description = models.TextField()
class ChildB(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True)
description = models.TextField()
childa = models.ForeignKey(ChildA)
这里重要的一点是parent_link=True
参数,它告诉Django使用这个字段声明来管理这两个模型的多表继承。
因此,您现在可以设置related_name='+'
以防止Django创建反向关系,或者您可以将related_name
设置为更独特的名称:
class ChildA(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True, related_name='child_a_here')
description = models.TextField()
class ChildB(Parent):
parent = models.OneToOneField(to=Parent, parent_link=True, related_name='child_b_here')
description = models.TextField()
childa = models.ForeignKey(ChildA)
答案 1 :(得分:0)
我对ChildB如何使用两个ChildA链接感到有点困惑,看起来你可能遗漏了模型中的一些关系字段?无论如何,我认为您正在寻找的是related_name
参数。
所以:
class ChildB(Parent):
description = models.TextField()
childa = models.ForeignKey(ChildA, related_name='b_children')
你可以这样做一个查询:
a = ChildA.objects.get(id=1)
print(a.b_children)
您可能也对abstract models感兴趣。