2010-09-27 63 views
1

models.py:可能的錯誤

class root(models.Model): 
     uid_string = models.CharField(max_length=255, unique=True) 

class tree(models.Model): 
     uid_string = models.ForeignKey(root, to_field='uid_string', db_column='uid_string') 

class shrub(models.Model): 
     uid_string = models.ForeignKey(root, to_field='uid_string') 

顯然,在shrub列將uid_string_idtree列將蜜蜂uid_string。 _id附錄被抑制。

如果我現在在做一個

rootentry = root(uid_string = "text") 
root.save() 

我得到不同的行爲,執行以下查詢:

>>> shrubentry = shrub(uid_string_id = rootentry.uid_string) 
>>> treeentry = tree(uid_string = rootentry.uid_string)                
Traceback (most recent call last):                     
    File "<console>", line 1, in <module> 
    File "/usr/local/lib/python2.6/site-packages/django/db/models/base.py", line 328, in __init__ 
    setattr(self, field.name, rel_obj) 
    File "/usr/local/lib/python2.6/site-packages/django/db/models/fields/related.py", line 318, in __set__ 
    self.field.name, self.field.rel.to._meta.object_name)) 
ValueError: Cannot assign "'text'": "tree.uid_string" must be a "root" instance. 
>>> 

明顯rootentry.uid_stringtext

回答

0

當foreignkeys打交道時,你需要使用對象像下面的實例。

treeentry = tree(uid_string = rootentry) 

順便說一下,使用CamelCase作爲類名稱。請閱讀http://www.python.org/dev/peps/pep-0008/

2

Django表現得和預期的一樣。爲了理解爲什麼我們將着眼於如何在外鍵關係的情況下將關鍵字參數傳遞給模型類的構造函數。

  1. 使用關係的名稱(uid_string)。在這種情況下,您必須通過相關型號的實例uid_string = rootentry)。

  2. 使用數據庫字段的名稱(uid_string_id)。在這裏你必須傳遞一個合適的類型的值。所以如果FK指向一個整數字段,傳遞一個整數;如果它指向文本,傳遞文本實例等。

現在讓我們看看你的代碼。我們將與第一線開始:

shrubentry = shrub(uid_string_id = rootentry.uid_string) 
shrubentry.save() # Succeeds 

您已經創建shrubroot之間的關係,而且還指定了一個自定義to_field鏈接。由於此列是文本字段,因此您可以通過rootentry.uid_string作爲uid_string_id關鍵字參數(上面列出的機制#2)的值。

還有另外一種方法可以表達你在上面做了什麼,而不使用字段名作爲關鍵字參數。這將是使用關係的名稱並傳遞根實例(上面列出的機制#1)。

shrubentry = shrub(uid_string = rootentry) 
shrubentry.save() # Succeeds 

現在讓我們來看看第二行

treeentry = tree(uid_string = rootentry.uid_string) # Raises error. 
# ValueError: Cannot assign "'text'": "tree.uid_string" must be a "root" instance. 

此行不同於第一行。您正在使用機制#1(關係名稱),因此Django需要root的實例作爲關鍵字參數的值。如果切換到機制#2(字段名稱):

treeentry = tree(uid_string_id = rootentry.uid_string) 
treeentry.save() # Succeeds 

現在出現有趣的部分。試試這個:

treeentry = tree(uid_string_id = rootentry.id) # No problem 
treeentry.save() # Blows up 
# IntegrityError: ... 
# DETAIL: Key (uid_string)=(2) is not present in table "app_root". 

上面代碼片段的第一行有效。但是,當您嘗試保存它時,數據庫將在root表的_uid_string_列中查找鍵「2」(即rootentry.id)。由於它不在那裏,save()失敗。

+0

謝謝你的回答。據我瞭解,你使用to_field ='uid_string'來指定關係,並簡單地通過db_column =「」來指定列的名稱。退出to_field將引用主鍵(id)。我錯了嗎? – tpm 2010-09-27 17:46:25

+0

你說得對。退出'to_field'是正確的。我的錯。我在編輯我的答案。 – 2010-09-27 17:50:13

+0

謝謝你的努力。但請再看一遍。這兩個模型都有一個'to_field'來指定列。除了'db_column'定義的列名外,模型是相同的。 – tpm 2010-09-27 19:04:10