2012-01-15 61 views
9

所有,困惑Django的外鍵,manytomanyfield,inlineformset_factories

我失去了一些東西有關Django的ForeingKeys VS ManyToManyFields底層模型的基礎。

假設我正在構建一個關於汽車的應用程序。我可能有以下類:

class Car(models.Model): 
    carName = models.CharField() 

class Manufacturer(models.Model): 
    manufacturerName = models.CharField() 

class Wheel(models.Model): 
    radius = models.IntegerField() 

到目前爲止好。現在這些類之間有一些關係。一輛汽車有一個製造商,並有(四)個輪胎。從概念上講,雖然有區別。製造商通過「聚合」相關;製造商可以與多輛汽車相關聯;刪除Car實例不應該導致該汽車的製造商也被刪除。車輪通過「組合」相關;與汽車相關的每四個車輪都與該車相關聯,並且僅與該車相關聯;刪除汽車,車輪也應該刪除。

因此,直觀地,這意味着我應該做到以下幾點:

class Car(models.Model): 
    carName = models.CharField() 
    manufacturer = models.ManyToManyField("Manufacturer") 
    wheels = models.ForeignKey("Wheel") 

最後,我想用inlineformset_factories,使用戶可以在大約一輛車,它的製造商和車輪都在填寫詳細信息同時。這樣的事情:

class CarForm(ModelForm): 
    class Meta: 
    model = Car 

class ManufacturerForm(ModelForm): 
    class Meta: 
    model = Manufacturer 

class WheelForm(ModelForm): 
    class Meta: 
    model = Wheel 

Manufacturer_formset = inlineformset_factory(Car,Manufacturer,formset=ManufacturerForm) 
Wheel_formset = inlineformset_factory(Car,Wheel,formset=WheelForm) 

但我發現的大多數文件表明,ForiegnKey應該從車輪到汽車。這看起來倒退了,因爲Wheel_formset會向用戶顯示Car(「carName」)而不是Wheel(「radius」)的所有字段。

只是打字這個問題的行爲讓我感到困惑。任何人都可以闡明我如何構建一個擁有所有汽車領域,然後是所有制造商領域,然後是所有車輪領域的形式。

感謝

回答

15

如果每節車廂都有生產廠家之一,那麼你應該使用外鍵從CarManufacturer。這將允許多輛汽車擁有相同的製造商,並且汽車被刪除時製造商不會被刪除。許多領域表明,一輛車可以有多個製造商。

Wheel應該有一個外鍵Car。這將允許多個車輪具有相同的車輛,並且當汽車被刪除時的默認Django行爲將是刪除車輪。

所以,你的模型應該是這個樣子:

class Manufacturer(models.Model): 
    name = models.CharField() 

class Car(models.Model): 
    name = models.CharField() 
    manufacturer = models.ForeignKey("Manufacturer") 

class Wheel(models.Model): 
    radius = models.IntegerField() 
    car = models.ForeignKey("Car") 

對你的看法,我先試試單獨寫意見的形式和表單集,並確保你之前瞭解你的模型之間的關係將它們集中在一起。

Stack Overflow question介紹瞭如何在同一時間(相當於CarWheel車型在你的情況)一起使用的一種形式和內聯表單集。對於製造商而言,您可能需要從CarFormexcludemanufacturer字段,然後在保存之前將其設置在您的視圖中。

... 
manufacturer = ManufacturerForm.save() 
car = CarForm.save(commit=False) 
car.manufacturer = manufacturer 
car.save() 
... 
+0

謝謝你的迴應。我可以證實,如果一輛汽車可以有多個製造商(比如它是由一個團隊製造的),那麼我應該使用一個ManyToManyField? – trubliphone 2012-01-16 04:38:42

+0

是的,如果汽車可以有多個製造商(並且製造商可以製造更多的汽車),則使用'ManyToManyField'。 – Alasdair 2012-01-16 10:22:54

+3

派對遲到了,但是外鍵不會是多對一的關係嗎? – 2014-11-04 14:36:26