2010-03-22 72 views
14

我认为这有点棘手,至少对我而言。 :)棘手的模型继承 - Django

所以,我有4种型号歌手贝斯手忍者

歌手,贝司手和忍者从Person继承。


问题是每个Person都可以是它的任何子类。

例如一个人可以是歌手和忍者。另一个人可以是低音歌手和忍者。另一个可以是三个。

我该如何组织我的模型?


帮助将不胜感激!

+4

海盗呢? :P – 2010-03-22 03:11:44

+4

你正在做什么样的项目?这听起来很棒!我想成为一个贝斯手 - 忍者混乱/邪恶。 – 2010-03-22 03:12:28

+3

有一次我有一个朋友在玩一个吟游诗人。他死了,他的心脏被取而代之,变得邪恶(不问)。一旦回到生活中,他扔掉琵琶,并拿起电吉他(再次,不要问),并鼓舞勇气在用金属哼唱的同时用他的刀子摘弦。很明显,它很棒。 – 2010-03-22 03:22:52

回答

15

多重继承不适用于数据库(并且您的Django模型最终需要映射到数据库),并且继承往往是模型化“角色”的不好方法(因为人们的角色确实发生了变化) 。我会歌手,贝司手和忍者的“角色”,作为人的子类,并通过外键连接:

class Singer(models.Model): 
    person = models.ForeignKey('Person') 
    # ... 

class Person(models.Model): 
    # ... 
+0

@Alex:通过多重继承代替角色,是否有另一种方式可以将它们合并在一起?我对使用FK将角色与Person类配对感到不安,因为Person的信息完全取决于他们是谁。也许我应该给这个更多的想法,非常感谢亚历克斯! – RadiantHex 2010-03-22 02:22:28

+0

这是要走的路,除非“歌手”只不过是一个描述符....在这种情况下,只需将'is_singer = models.BooleanField()'添加到'Person'模型将为简化模型更快的查询 – 2010-03-22 02:22:47

+0

这些是角色,而不是子类。传统的基于类的_single inheritance_分类法中的子类是相互排斥的。例如,狗,猫和兔子都可以从哺乳动物继承,但没有同时是狗和兔子的动物。支持多继承的语言更容易理解这种事情,但在这种情况下,我同意亚历克斯的观点:使用继承将是一个模型错误,即使它很容易工作。 – 2010-03-22 02:35:48

2

我同意角色的解决方案,由亚历克斯所描绘。你有什么不是不同的人的子类。你可以拥有不同的角色。但是我听到你说:“嘿,忍者可以拥有一个属性”numberOfStars“,而歌手可以拥有一个属性”highestNote“。同接口:忍者可以有方法throwStar()和消失(),而歌手可以唱歌()和getWasted(),并且贝司播放器可以有goFunky()和slapPop()

您在这里遇到的情况是数据模型需要非常松散的模式。如此宽松,实际上,你根本没有任何图式,如果歌手决定拿低音和即兴曲调,那很好,如果他想扮演一个忍者,而你叫做throwStar,它会返回一个错误,因为他没有明星,但你原则上可以给歌星分配星星,让他投掷星星。

你所冒险的是本体论的世界,而不是图式。你有一个资源,它是“某些东西”,这个东西可以是某种类型,有一些属性等等。某些属性的存在可以推断出类型,或者某种类型的存在可以推断出其他类型。您无法使用简单的django数据模型轻松描述这些信息。你需要的是上下文感知,推理的图形存储,比如AllegroGraph,或者使用rdflib实现你的黑客解决方案。

+2

您在这里混合了多个问题。歌手和忍者可能需要不同的属性,但绝不意味着你突然拥有完全开放的动态模式。表达一类人所特有的知识的明显且简单的方法是除了人表之外,还有一个歌手表,其中包含关于歌手的事实,相应的忍者表等等。所有的表格都有一个person_id的PK,适当的时候使用FKs。 – 2010-06-05 23:13:07

3

在原则上,你可以这样做以下:

class Role(models.Model):  
    ...... 

class Ninja(Role): 
    ....... 

class Person(models.Model): 
     roles = models.ManyToManyField(Role) 

但是你在运行到该Person.roles.objects.all()只能给你角色的实例的问题。因此,您需要一种方法将角色的每个实例转换为合适的子类,例如Ninja或Pirate。这是一个讨论这个问题的线索的链接。

http://groups.google.com/group/django-users/browse_thread/thread/f4241bc16455f92d/7268c3f7bca6b046

因此,在短期亚历克斯和Stefano给比我有用的答案。

1

你可以让你所有的职业(忍者,贝司手....)从继承人在模型中,然后使用功能isinstance在后端代码的职业区分。