2014-07-22 51 views
9

假設我有一個這樣的模型。Django外鍵訪問如何工作

class Job(models.Model): 
    client = models.ForeignKey(Contacts, null=True) 

並讓我說我有工作j。我知道我可以訪問屬於j中的客戶端這樣

j.client 

但也有

j.client_id 

所以我的問題是如何訪問j.client工作?

是否django存儲client__id然後當j.client被調用它做查詢來找到正確的對象?

或者是存儲到j的對象引用,並訪問client__id正在從聯繫對象獲取id?

我看了看周圍的源代碼一下,但找不到答案,我的問題

+0

[Django什麼時候查找外鍵的主鍵?]的可能重複(http://stackoverflow.com/questions/13631211/when-does-django-look-up-the-primary-key-of -foreign-keys) –

回答

8

這在文檔中進行了說明:
https://docs.djangoproject.com/en/dev/ref/models/fields/#database-representation

在數據庫中只有client_id場(單下劃線)

在模型實例上,您將擁有client屬性,當您訪問它時,這將導致Django從數據庫加載相關對象並作爲另一個模型實例實例化。

您還將擁有client_id屬性(一個下劃線),該屬性具有存儲在db字段中的相關對象的主鍵值。

在做ORM查詢,你可以使用client__id(雙下劃線)語法來查找針對領域的相關模型,例如還可以做client__name如果Client模型具有name場。這將成爲跨兩個模型的SQL JOIN查詢。

Job.objects.get(client__id=1) 
Job.objects.filter(client__name='John') 

client = Client.objects.get(pk=1) 
Job.objects.get(client=client) 
+0

是的,我注意到我的錯誤,並編輯了正確反映訪問權限的問題。真棒這是我正在尋找的確認。我懷疑是這種情況,謝謝隊友! –

2

j.client給你models.Model對象。您可以訪問它的屬性,如...

client = j.client 

id = client.id 
name = client.name 

但不應該有一個j.client__id字段。您應該使用j.client.id來獲取id字段。儘管您可以使用j.client__id字段來執行過濾器等操作。

所以,

id = j.client.id # good 
id = j.client__id # bad 

job = Job.objects.get(client__id=1) # good 
job = Job.objects.get(client.id=1) # bad 
+0

對不起,我不打算把額外的_ 有一個client_id字段自己嘗試 –

+0

從Django的文檔 - 「在幕後,Django追加」_id「字段名稱來創建其數據庫列名稱「。 –

+0

我不確定爲什麼有人會根據錯誤輸入的問題來回答我的答案。 –

9

你可能說什麼是clientclient_id(單下劃線)。

client_id屬性是一個常規(整數)屬性。這是保存到數據庫的外鍵。即使您將ForeignKey指定爲client,您也只會在數據庫中看到client_id列。

client屬性是一個對象描述符實例。這是一個覆蓋__get____set__方法的特殊類,因此設置和訪問該屬性將調用該類的方法。這是讓您訪問實際相關模型實例的魔法。根據client_id屬性,__get__將從數據庫中檢索正確的模型實例(如果它尚未加載)。 __set__也會將client_id屬性設置爲相關對象的主鍵,因此client_id始終是最新的。

請注意,該屬性在查詢查找中也可用,並且非常方便。例如,如果你只有一個異物的主鍵,而不是模型實例本身,下面的查詢看起來非常相似:

job = Job.objects.filter(client__id=pk) 
job = Job.objects.filter(client_id=pk) 

然而,下方的第一個查詢訪問相關對象進行的屬性(雙下劃線)並執行OUTER JOIN。第二個查詢只訪問本地屬性,因此不必執行OUTER JOIN語句並保存性能。

+0

是的,我已經改變了我的問題,發佈一分鐘後發現錯誤。你們對我來說太快了。「<哈哈 –