棘手的模型继承 - Django
我觉得这个问题有点复杂,至少对我来说是这样。:)
我有四个模型,分别是人、歌手、贝斯手和忍者。
歌手、贝斯手和忍者都是从人这个模型派生出来的。
问题是,每个人都可以是它的子类中的任何一个。
比如说,一个人可以既是歌手又是忍者。另一个人可以是贝斯手和忍者。还有一个人可以是这三者的结合。
我应该怎么组织我的模型呢?
非常感谢任何帮助!
4 个回答
我同意Alex提到的角色解决方案。你所拥有的并不是不同类型的人,而是一个人可以扮演的不同角色。
但我听到你说:“嘿,忍者可以有一个属性叫‘星星数量’,而歌手可以有一个属性叫‘最高音’。就像接口一样:忍者可以有方法throwStar()和disappear(),而歌手可以有sing()和getWasted(),贝斯手可以有goFunky()和slapPop()。”
你这里遇到的情况是,你的数据模型需要一个非常宽松的结构。宽松到实际上,你根本没有结构。如果歌手决定拿起贝斯即兴演奏,那没问题。如果他想当忍者,调用throwStar时会报错,因为他没有星星,但原则上你可以给歌手分配星星,让他也能扔星星。
你现在进入的是本体论的世界,而不是传统的结构。你有一个资源,也就是“某种东西”,这个东西可以有某种类型,拥有一些属性等等。某些属性的存在可以推断出类型,或者某种类型的存在可以推断出其他类型。用简单的django数据模型很难描述这些信息。你需要的是一个能够理解上下文并进行推理的图形存储,比如AllegroGraph,或者用rdflib实现你自己的解决方案。
原则上,你可以做类似下面的事情:
class Role(models.Model):
......
class Ninja(Role):
.......
class Person(models.Model):
roles = models.ManyToManyField(Role)
但是你会遇到一个问题,Person.roles.objects.all() 只能给你角色(Role)的实例。所以你需要一个方法,把每个角色实例转换成合适的子类,比如忍者(Ninja)或海盗(Pirate)。这里有一个链接,讨论了这个问题。
http://groups.google.com/group/django-users/browse_thread/thread/f4241bc16455f92d/7268c3f7bca6b046
总之,Alex 和 Stefano 给出的答案比我更有用。
多重继承在数据库中不太好用(而且你的Django模型最终需要映射到数据库),而且用继承来表示“角色”通常不是个好主意(因为人的角色是会变化的)。我会把歌手、贝斯手和忍者看作“角色”,而不是作为人的子类,并通过外键来连接它们:
class Singer(models.Model):
person = models.ForeignKey('Person')
# ...
class Person(models.Model):
# ...