2009-07-11 111 views
10

基本上,我有一個模型,我創建了許多其他類共享的超類,然後每個類都有一些彼此不同的獨特功能。假設類A是超類,而類B,C和D是該類的子類。Django模型繼承和外鍵

B類和C類都可以有D類的倍數,但我已經看到最好把外鍵關係放在D類中,然後引用它的父類。現在在其他語言中,我可以簡單地說它與類A具有ForeignKey關係,然後該語言識別類的真實類型。但是,我不認爲它是如何與Python協同工作的。

追求這個問題的最佳方式是什麼?

編輯:這大致就是我的意思是......

class A(models.Model): 
    field = models.TextField() 

class B(A): 
    other = <class specific functionality> 

class C(A): 
    other2 = <different functionality> 

class D(A): 
    #I would like class D to have a foreign key to either B or C, but not both. 

從本質上講,B類和C類都有多個類D的。但是一個特定的D類只屬於其中之一。

+0

你能解釋爲什麼你需要繼承嗎? – Evgeny 2009-07-11 22:25:56

+0

有一個相關的問題有一些很好的答案,這可能有助於:https://stackoverflow.com/questions/1114767/django-model-inheritance-and-foreign-keys – Miranda 2017-12-07 07:28:36

回答

3

Django Docs

例如,如果你正在建設一個 數據庫的「場所」,你將建立 非常標準的東西,如地址, 電話號碼等在數據庫。 然後,如果你想建立的 地方頂部的 數據庫的餐館,而不是重複自己 並在 餐廳模型複製這些領域,你可以做 餐廳有OneToOneField到 地方(因爲餐廳「是一個」 的地方;實際上,爲了處理這個問題,你通常會使用繼承,其中 涉及隱式的一對一關係)。

通常情況下,您將只有Restaurant繼承自Place。可悲的是,你需要什麼,我認爲一個黑客:從子做出一個對一個參考進行超(RestaurantPlace

+0

是不是django默認提供這種一對一的引用?例如對於多表繼承模型,「restaurant.place」返回Place的相應實例,而不需要用戶定義除繼承之外的任何關係。 – 2012-01-26 14:19:13

1

我看到這裏有一個問題:

class D(A): 
    #D has foreign key to either B or C, but not both. 

不能做到這一點。您必須添加兩者,因爲在SQL中,列必須精確定義。

即使像你這樣的繼承模型已經與syncdb編譯 - 他們似乎並不像你期望的那樣 - 至少我不能讓它們工作。我無法解釋爲什麼。

這是FK如何工作在Django

class A(models.Model): 
    a = models.CharField(max_length=5) 

class B(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    b = models.CharField(max_length=5) 

class D(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    parent = model.ForeignKey(B, related_name='D') 

這種方式可以有效地具有d的倍數B.

在模型繼承(如B類(A))不爲工作我會期待它。也許別人可以更好地解釋它。

看看this doc頁面。這是關於Django的多對一關係。

b = B() 
b.D_set.create(...) 
+0

我的問題是,我想類d屬於無論是A類還是B類,而不是兩者。我會在我的問題中澄清。 – AlbertoPL 2009-07-11 22:59:24

1

的一種方法是如下添加一箇中間類:

class A(Model): 
    class Meta(Model.Meta): 
     abstract = True 
    # common definitions here 

class Target(A): 
    # this is the target for links from D - you then need to access the 
    # subclass through ".b" or ".c" 
    # (no fields here) 

class B(Target): 
    # additional fields here 

class C(Target): 
    # additional fields here   

class D(A): 
    b_or_c = ForeignKey(Target) 
    def resolve_target(self): 
     # this does the work for you in testing for whether it is linked 
     # to a b or c instance 
     try: 
      return self.b_or_c.b 
     except B.DoesNotExist: 
      return self.b_or_c.c 

使用中間類(目標)保證只會有從d一條鏈路到B或C.這是否合理?有關更多信息,請參閱http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance

在你的數據庫將有目標,B,C和d表,但不是一個,因爲被標記爲抽象的(相反,與上一個屬性欄將出現在目標和d)。

[警告:我實際上沒有試過這個代碼 - 任何更正歡迎!]