2016-11-14 85 views
1

models.pyDjango:將foreignkey字段賦給對象?

class Order(TimeStampedModel): 
    name = models.CharField(max_length=50) 

class Payment(TimeStampedModel): 
    order = models.ForeignKey(
     'orders.Order', 
     null=True, 
     blank=True, 
     unique=True, 
    ) 

我想要做的是創造Payment第一,並將其​​添加到Order

比方說Order已經創建沒有payment字段。

< 1>

In [1]: order = Order.objects.first() 

In [2]: payment = Payment.objects.create() 

In [3]: order.payment = payment 

In [4]: order.save() 

< 2>

In [7]: order.payment_set.add(payment) 

我想知道的是什麼< 1>< 2>之間的區別。哪一個是正確的?

回答

1

您的第一個示例可以重寫以減少數據庫使用(因爲它目前顯示,它將使INSERTpayment=NULL,其次是UPDATE)。這應該是更好的:

order = Order.objects.first() 
payment = Payment.objects.create(order=order) 

現在,問題。兩種方法幾乎完全相同。但是,如果您使用的是django> = 1.9,則存在差異。 .add現在默認執行批量插入,而不是在每個實例上調用save。這意味着,如果您有連接到您的Payment模型像post_savepost_create任何信號,你會不會讓他們執行的,除非你明確指定bulk=False

order.payment_set.add(payment, bulk=False) 
0

我認爲你可能有你的關係,圍繞着錯誤的方式你第一場景;第3行和第4行應該是:

payment.order = order 
payment.save() 

1.在實例上設置FK。

您的付款的保存方法被調用,並且您將單個付款與單個訂單相關聯。 Payment.save被稱爲,發射保存相關信號。

2:使用RelatedManager.add method

您實際上可以使用此方法一次添加多個關聯。因此,例如,你可以用一個訂單多支付使用相關聯:默認情況下,因爲Django的1.9

order.payment_set.add(payment_1, payment_2, ... payment_N) 

重要的是,在沒有創建支付他們的save()方法被調用,這樣你就不會得到保存相關信號射擊。

在保存信號發射的重要性:

這是很常見的Django應用程序使用signals。它們提供了一種強大的方式來爲應用程序添加功能,而不會混淆模型邏輯。如果您的應用程序正在使用它們,請使用RelatedManager.add方法添加關聯,因爲保存相關信號不會觸發。