2008-08-30 52 views
59

我正在考慮使用Django作爲我開始的項目(fyi,基於瀏覽器的遊戲),我最喜歡的功能之一是使用syncdb自動創建數據庫表基於我定義的Django模型(我似乎無法在其他任何框架中找到的功能)。 我已經想這是好得是真實的,當我看到這個在documentation在Django中更改數據庫表

執行syncdb不會改變現有的表

執行syncdb只會創造尚未安裝哪些車型表。它永遠不會發出ALTER TABLE語句來匹配安裝後對模型類所做的更改。更改模型類和數據庫架構往往涉及某種形式的模糊,在這種情況下,Django的必須在正確的變化作出猜測。在這個過程中,關鍵數據可能會丟失。

如果您對模型進行了更改並希望更改數據庫表以匹配,請使用sql命令顯示新的SQL結構並將其與現有表模式進行比較以計算出更改。

似乎改變現有的表格將不得不「手工」完成。

我想知道什麼是做到這一點的最好辦法。想到兩種解決方案:

  • 正如文檔所述,請在數據庫中手動進行更改;
  • 執行數據庫備份,擦除它,再次創建表(使用syncdb,因爲現在它正在從頭開始創建表)並導入備份的數據(如果數據庫很大,這可能需要很長時間)

有什麼想法?

回答

59

手動執行SQL更改和dump/reload都是選項,但您可能還想查看Django的一些schema-evolution軟件包。最成熟的選項是django-evolutionSouth

編輯:嘿,這裏來dmigrations

UPDATE:既然這個答案最初寫,django-evolutiondmigrations兼得不再積極開發和South已成爲Django的架構遷移的事實標準。南部的部分甚至可能會在下一個版本或兩個版本中集成到Django中。

UPDATE:根據南(由安德魯·戈德溫,南方的作者撰寫)到架構的遷移框架包含在Django 1.7+。

+1

django-evolution似乎工作正常,謝謝!值得指出的是,必須從頭開始使用它(它不計算來自現有SQL的必要更改)。 – gatoatigrado 2009-09-07 18:57:17

9

一個好方法是通過燈具,特別是initial_data燈具。

的燈具,是包含數據庫的序列化內容的文件的集合。所以,它就像具有數據庫的備份,但因爲它的東西Django是意識到這一點更容易使用,將有額外的好處,當你來到做這樣的事情的單元測試。

您可以使用django-admin.py dumpdata從當前數據庫中的數據創建一個夾具。默認情況下,數據採用JSON格式,但其他選項(如XML)可用。存儲燈具的好地方是應用程序目錄的fixtures子目錄。

您可以使用django-admin.py loaddata加載修補程序,但更重要的是,如果您的夾具具有像initial_data.json這樣的名稱,那麼當您執行syncdb時它將自動加載,從而節省您自己導入它的麻煩。

另一個好處是,當您運行manage.py test來運行您的單元測試時,臨時測試數據庫也將加載初始數據夾具。

當然,當您將屬性添加到模型和列到數據庫時,這會起作用。如果從數據庫中刪除一列,則需要更新夾具以刪除該列的數據,這可能並不簡單。

在開發過程中做很多小的數據庫更改時,此功能效果最佳。爲了更新生產數據庫,手動生成的SQL腳本通常可以發揮最佳效果。

4

我一直在使用django-evolution。注意事項包括:

  • 它的自動建議已經一致爛了;和
  • 其指紋函數爲不同平臺上的同一數據庫返回不同的值。

這就是說,我發現自定義schema_evolution.py方法得心應手。要解決指紋問題,我建議這樣的代碼:

BEFORE = 'fv1:-436177719' # first fingerprint 
BEFORE64 = 'fv1:-108578349625146375' # same, but on 64-bit Linux 
AFTER = 'fv1:-2132605944' 
AFTER64 = 'fv1:-3559032165562222486' 

fingerprints = [ 
    BEFORE, AFTER, 
    BEFORE64, AFTER64, 
    ] 

CHANGESQL = """ 
    /* put your SQL code to make the changes here */ 
    """ 

evolutions = [ 
    ((BEFORE, AFTER), CHANGESQL), 
    ((BEFORE64, AFTER64), CHANGESQL) 
    ] 

如果我有更多的指紋和更改,我會重新考慮它。在此之前,將其變得更清潔將會從其他方面竊取開發時間。

編輯:鑑於我手動構建我的更改無論如何,我會嘗試下次嘗試dmigrations

+0

對於簡單的演化,例如添加,刪除或重命名字段,django-evolution對我而言效果很好。有時我必須添加一個我不想在模型中指定的默認值(而是告訴django-evolution只是爲現有字段設置),但除此之外 - 沒有抱怨。 – 2009-07-11 11:30:28

3

django-command-extensions是一個django庫,它提供了一些額外的manage.py命令。其中之一是sqldiff,它應該爲您提供更新到新模型所需的sql。然而,它被列爲「非常實驗」。

2

到目前爲止,在我的公司我們已經使用了手動方法。最適合你的是非常依賴你的開發風格。

我們在生產系統中通常沒有太多的模式更改,並且從開發到生產服務器的部署也有所規範。無論何時我們推出(每年10-20次),我們會對當前和即將到來的生產分支進行填寫比較,以檢查所有代碼並注意生產服務器上必須更改的內容。所需的更改可能是其他依賴項,對設置文件的更改以及對數據庫的更改。

這對我們很有效。把它全部自動化是一個利基的願景,但對我們來說很難 - 也許我們可以管理遷移,但是我們仍然需要處理額外的庫,服務器以及任何依賴關係。

2

Django書籍解釋瞭如何手工完成。

http://www.djangobook.com/en/2.0/chapter10/

我已經做了這樣很多次,這是非常靈活的,允許你在表中留下的數據,同時從模型中移除。

我最近開始使用South。它看起來不太靈活(或者我可能只需要閱讀文檔)。但是可以節省一些打字的時間。有時你會設法讓它與數據庫不同步,這是一場噩夢。似乎只要繼續使用它就可以正常工作。它似乎將模型和實際數據庫連接在一起,根據您的情況,這可能會也可能不是一件好事

2

Django 1.7(當前正在開發中)是adding native support用於模式遷移manage.py migratemanage.py makemigrationsmigrate棄用syncdb)。