2010-03-22 134 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在後端代碼的職業區分。