2010-08-27 87 views
0

在Django中我有論文型號:如何建模M2M關係下相關的表可以是一個城市,一個區域(州)或國家

class Artist(models.Model): 
    name = models.CharField(max_length=128) 
    born_place = models.ForeignKey(???) 
    dead_place = models.ForeignKey(???) 
    live_places = models.ManyToManyField(???) 
    work_places = models.ManyToManyField(???) 

class Country(models.Model): 
    iso = models.CharField(max_length=2, primary_key=True) 
    name = models.CharField(max_length=50) 

class Region(models.Model): 
    iso = models.CharField(max_length=2, blank=True) 
    name = models.CharField(max_length=150) 
    country = models.ForeignKey('Country') 

class City(models.Model): 
    name = models.CharField(max_length=150) 
    region = models.ForeignKey('Region') 

所有地方born_placedead_placelive_places,work_places)可以是CityRegionCountry。而City應該有一個Region,而Region應該有一個Country

我該如何做到這一點?

+0

對不起,遲交。感謝所有的答案。他們都是很好的答案。最後我選擇模型繼承解決方案。我選擇它是因爲它適合我的需求和結構非常好(每個類型(國家等)都有一個連貫的表格)。與* o.elias *提出的模型唯一的區別在於我沒有在Territory類中放置任何字段。這樣國家,地區和城市的表格更加連貫*(所有的信息都在同一個地方)。我需要這樣做,因爲有些表可以直接進行諮詢/編輯(例如使用MS Access)。 – Etienne 2010-09-03 16:00:52

回答

1

您還可以使用模型繼承

class Territory(models.Model): 
    name = models.CharField(max_length=150) 

class Country(Territory): 
    iso = models.CharField(max_length=2, primary_key=True) 

class Region(Territory): 
    iso = models.CharField(max_length=2, blank=True) 
    country = models.ForeignKey('Country') 

class City(Territory): 
    region = models.ForeignKey('Region') 

class Artist(models.Model): 
    name = models.CharField(max_length=128) 
    born_place = models.ForeignKey(Territory) 
    dead_place = models.ForeignKey(Territory) 
    live_places = models.ManyToManyField(Territory) 
    work_places = models.ManyToManyField(Territory) 

最好的問候!

+0

嗯,有趣的方法。我需要用這個來看看所有的含義(管理員,表格結構等)。 – Etienne 2010-08-27 14:01:38

1

所有地方(born_place,dead_place,live_places,work_places)可以是城市或地區或國家。

你在這種情況下需要的是generic foreign key。在Django中,這可以通過方便的contenttypes框架來實現。

從文檔:

有三個部分,以建立一個GenericForeignKey:

  1. 給你的模型一個ForeignKey到的ContentType。

  2. 爲您的模型提供一個可以存儲您將與之相關的模型的主鍵值的字段。 (對於大多數模型,這意味着IntegerField或PositiveIntegerField。)該字段必須與通用關係中涉及的模型的主鍵類型相同。例如,如果使用IntegerField,那麼將無法與使用CharField作爲主鍵的模型形成通用關係。

  3. 爲您的模型指定一個GenericForeignKey,並將其傳遞給上述兩個字段的名稱。如果這些字段被命名爲「content_type」和「object_id」,那麼您可以忽略它 - 這些是GenericForeignKey將查找的默認字段名稱。

+0

也是一個有趣的解決方案。我需要玩它。但我的感覺是,通用的foreignkey更適合於以其他方式工作(比如在標籤示例中,您將標籤添加到許多模型中)。就我而言,如果我理解正確,我會將藝術家添加到國家或地區或城市。我認爲它會起作用,但對我來說看起來不那麼優雅。但我可能是錯的。 – Etienne 2010-08-27 14:23:44

0

看看Django的通用關係herehere,這將讓你關鍵不同類型的對象,而不是僅在特定的一個。

1

好吧..也許你可以使用泛型關係。但我認爲你可以通過跳出框框來解決你的一些問題。

我想說,你可以創建一個領土模型,而不是國家,地區和城市;然後用recursive relationship

class Territory(models.Model): 
    iso = models.CharField(max_length=2, blank=True) 
    name = models.CharField(max_length=150) 
    parent = models.ForeignKey('self') 

這會爲你的領土層次結構,所以現在只要你喜歡,你可以使用盡可能多的部門(爲爲例,大陸,行星,社區),你不會有改變你楷模。至於藝術家,你可以這樣做:

class Artist(models.Model): 
    name = models.CharField(max_length=128) 
    born_place = models.ForeignKey(Territory) 
    dead_place = models.ForeignKey(Territory) 
    live_places = models.ManyToManyField(Territory) 
    work_places = models.ManyToManyField(Territory) 

所以現在......在born_place可以是一個城市,一個地區,一個星球......任何你想要的!我想這是你的問題。我不是django的專家,這只是O.O.P中解決這類問題的一種通用方法。

+0

當我發佈我的問題後,我想到了這個解決方案。我的版本唯一的區別是我在Territory類中有一個「kind」字段(具有可能值的選擇字段:country,region,city)。這樣我就可以只過濾城市或國家等等。更重要的是,我可以將城市的父母作爲一個地區,而該地區的父母應該是一個國家。 目前,這是我最喜歡的解決方案。但是我需要評估更多其他解決方案,泛型關係和模型繼承。 – Etienne 2010-08-27 14:10:03

+0

哦耶!我忘了「kind」字段,我通常把它稱爲「type」。 使用繼承的缺點是如果你想引入新的「types」或「種類」,那麼你將不得不修改你的代碼,這就是爲什麼繼承是一個很好的解決方案,當你有一定數量的元素不會在時間上發生變化的時候..女巫可能是你的情況......我經常在處理更動態創建的「類別」和「子類別」時使用此解決方案 – pleasedontbelong 2010-08-27 15:30:53

+0

關於「kind」我通常在Python中使用它(而不是在Django中)而不是「type」來避免問題,因爲「type」是python中的一個關鍵字。但我同意「類型」是一個更好的定義。 merci指出了繼承和解決方案之間的區別。你對泛型關係方法有任何意見嗎? – Etienne 2010-08-27 16:12:18

相關問題