2014-09-03 74 views
4

有很多地方建議使用ForeignKey一對多或多對一的關係,但我很努力去理解這將如何工作,而不反轉依賴。Django一對多的領域沒有扭轉依賴關係

例如:

我有這些2級的應用程序,「定居點」和「支付」,理想情況下,定居點並不需要了解有關付款,因爲在創建支付記錄定居點已經作出後,以及支付記錄可以包含多個結算。

住區模式:

class Settlement(models.Model): 
    ... 

支付模式:

class Payment(models.Model): 
    settlements = models.ManyToManyField('Settlement') 
    .... 

這帶來了一個基本架構的警告,即結算可以屬於多個付款,這是不應該的。

要執行和解不能屬於一個以上的付款記錄,我將不得不把支付foreignkey在結算:

住區模式:

class Settlement(models.Model): 
    payment = models.ForeignKey('Payment') 
    ... 

支付模式:

class Payment(models.Model): 
    .... 

雖然這強制了模式的有效性,但似乎依賴已經扭轉,現在解決方案需要知道付款,只是製造了ese 2個應用程序緊密耦合。此外,我還需要創建付款欄位爲空的結算記錄,創建付款記錄,然後返回結算記錄來連接付款記錄,這似乎是錯誤的。

+0

爲什麼第二種方法似乎是錯誤的?從概念上講,在現實生活中,您需要先創建結算實例,然後進行支付,然後綁定它們。 – levi 2014-09-03 03:06:12

+0

也許一個更好的概念化關係的方式是'屬於' - 結算1,3和9屬於付款4。 – DivinusVox 2014-09-03 03:12:00

回答

2

雖然模式可能有意義,但Settlement上的外鍵鏈接到Payment,但您的應用程序不必具有該關係(或在數據庫上執行該關係)。我會假設Settlement不能更改,並且您只能使用Payment應用程序。

只需創建您自己的中間模型/表格,並鏈接付款。這就像有一個ManyToMany關係,但你可以強制它的約束。

class Payment(models.Model): 
    # your fields go here 

class Invoice(models.Model): 
    settlement = models.OneToOneField('settlements.Settlement') 
    payment = models.ForeignKey(Payment) 

注意OneToOneField。這實質上是一個具有唯一約束的外鍵。我們正在模擬ManyToMany中間表,但將settlement限制爲僅在發票表中具有單個記錄。

我應該注意到,因爲我們在這裏創建一個新表,所以未來的查詢可能會很慢,因爲需要額外的連接。如果修改Settlement模型以包含ForeignKey,則它將從標準化意義上執行並且看起來更好。