2011-04-05 61 views
3

我有一個從模型Object繼承的模型ThreadedComment。 ThreadedComment沒有自己的唯一主鍵,依賴於Object的主鍵(「ID」)。這是該模型是如何構建的:Django在遷移到1.2.5後測試失敗 - 子模型的主鍵問題

class Object(models.Model): 
    permalink = models.CharField(max_length=128) 
    status = models.IntegerField() 
    version = models.IntegerField() 

class ThreadedComment(Object): 
    parent = models.ForeignKey('self', null=True, blank=True, default=None, related_name='children') 
    parent_object = models.OneToOneField(Object, parent_link=True) 
    # other fields follow 

這很好工作,直到Django的1.2.3,但是當我升級到1.2.5的Django(1.3有同樣的問題),這種情況發生的時候我試圖運行任何測試:

Error: Database test_db couldn't be flushed. Possible reasons: 
    * The database isn't running or isn't configured correctly. 
    * At least one of the expected database tables doesn't exist. 
    * The SQL was invalid. 
Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. 
The full error: relation "threadedcomments_threadedcomment_id_seq" does not exist 
LINE 1: SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1... 

問題是用「sqlflush」命令生成並執行SQL文件。有問題的行是:

SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false); 

這顯然失敗,因爲該表中沒有「id」列。

什麼是野趣,Django的1.2.3版本產生相似的輸出:

SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false); 

但測試的推移反正所以我沒有注意到之前的問題。

我在這裏做錯了什麼?模型定義是否不正確,即,我是否需要在線索評論中有一個主鍵,即使我不需要它與對象具有一對一的關係?那麼它是如何從1.0到1.1一直工作到1.2.3,現在又在1.2.5中突破的呢?

回答

0

我不能在trunk或1.2.3上重現它;我創建了應用程序「threadedcomments」和車型新項目,你貼有以下結果:

BEGIN; 
TRUNCATE "threadedcomments_threadedcomment", "auth_permission", "auth_group", "auth_group_permissions", "django_session", "auth_user_groups", "auth_user_user_permissions", "threadedcomments_object", "auth_message", "django_site", "auth_user", "django_content_type"; 
SELECT setval(pg_get_serial_sequence('"auth_permission"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_group"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_user"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_message"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"django_content_type"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"django_site"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"threadedcomments_object"','id'), 1, false); 
COMMIT; 

序列threadedcomments_threadedcomment_id_seq,從未創建和Django不嘗試刷新它。我不認爲這是一個版本變化相關的錯誤(而是一直存在的東西,但沒有被注意到)。

+0

它適用於1.2.3。它在1.2.5和1.3上失敗(至少那些是我測試的版本)。此外,請不要在threadedcomments應用程序中對其進行測試,而只需創建一個類似我所描述的模型。我們正在Filmaster上使用大量黑客入侵的threadcomments應用程序。另一種複製方式:只需從hg clone https://bitbucket.org/filmaster/filmaster-reloaded獲取源代碼,然後在1.2.3和1.2.5上運行python manage.py sqlflush來查看我的意思。 – michuk 2011-04-06 00:10:48

0

你說:「ThreadedComment沒有自己的唯一主鍵,依賴於Object的promary [原文]鍵('ID')。」 Django需要將一個字段標識爲主鍵。請參閱Automatic primary key fields

更多細節。 。 。

函數pg_get_serial_sequence()返回特定列使用的序列的名稱。因此,以下語句表示「獲取表'threadedcomments_threadedcomment'中'id'列所用序列的名稱,將序列的last_value字段設置爲1,並在nextval()被調用時返回1.

SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false); 

但這句話

SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false); 

手段 「將名爲 'threadedcomments_threadedcomment_id_seq' 1序列的LAST_VALUE領域,並在下次返回1 NEXTVAL()被調用。」

我的猜測是Django用來命名se的算法版本之間會發生變化。我見過其他系統進行類似的更改,因爲通過連接表名和列名建立的標識符變得太長了。我認爲Oracle標識符有30個字符的限制;您的標識符是39個字符。我見過Rails生成70多個字符標識符,它們在PostgreSQL上打破(63或64個字符限制)。

+0

「Django需要將一個字段標識爲主鍵」 - 是的,我知道這一點,但它用於在父表中的ID而不是子表中正常工作。因爲這裏的關係是一對一的,所以在子表中複製ID沒有任何意義。 我應該創建一個只有滿足django的primary_key = True的fake_id字段嗎?這聽起來像一個可怕的解決方法。 – michuk 2011-04-07 20:37:38

+0

我想說你可能只需要在parent_object上設置'primary_key = True'。從我發佈的鏈接中,「OneToOneField類用於自動成爲模型的主鍵,這不再是真實的(儘管如果你喜歡,你可以手動傳遞primary_key參數)」。 – 2011-04-07 21:27:27

+0

父對象已經有了primary_key = True。這原來是一個django錯誤。更多的細節在我自己的答案下面這個問題。 – michuk 2011-04-19 18:09:43