2012-10-11 62 views
63

我想從一個文本字段刪除空=真不能ALTER TABLE:南:因爲它已經掛起的觸發事件

- footer=models.TextField(null=True, blank=True) 
+ footer=models.TextField(blank=True, default='') 

我創建的模式遷移:

manage.py schemamigration fooapp --auto 

由於一些頁腳列包含

django.db.utils.IntegrityError: column "footer" contains null values 

我已將此添加到架構遷移:NULL,如果我跑遷移我得到這個錯誤

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
     sender.footer='' 
     sender.save() 

現在,我得到:

django.db.utils.DatabaseError: cannot ALTER TABLE "fooapp_emailsender" because it has pending trigger events 

有什麼不對?

+0

這個問題是類似的:http://stackoverflow.com/questions/28429933/django-migrations-using-runpython-to-commit-changes並有更有用的答案給我。 – SpoonMeiser

回答

73

每次遷移都在一個事務中。在PostgreSQL中,您不得更新表,然後在一個事務中更改表模式。

您需要拆分數據遷移和模式遷移。首先,此代碼創建數據遷移:

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
    sender.footer='' 
    sender.save() 

然後創建架構遷移:

manage.py schemamigration fooapp --auto 

現在你有兩個交易分兩步遷移應該工作。

+5

PostgreSQL可能會改變它對這種事務的行爲,因爲我在設備(PostgreSQL 9.1)上發生故障時,在我的開發機器(PostgreSQL 9.4)上設法運行了數據和模式更改的遷移。 –

11

剛剛遇到這個問題。您還可以在模式遷移中使用db.start_transaction()和db.commit_transaction()將數據更改從模式更改中分離出來。可能不那麼幹淨,以至於不能進行單獨的數據遷移,但在我的情況下,我需要模式,數據,然後再進行另一個模式遷移,因此我決定一次完成所有工作。

+5

此解決方案的問題是:如果在db.commit_transaction()之後遷移失敗會發生什麼情況?如果您需要這樣的話,我優先使用三種遷移:schema-mig,data-mig,schema-mig。 – guettli

+0

參見:http://django.readthedocs.io/en/latest/ref/migration-operations.html 對於支持DDL事務(SQLite和PostgreSQL)的數據庫,除了RunPython操作外,還沒有任何自動添加的事務爲每個遷移創建的事務。因此,例如,在PostgreSQL上,您應該避免將模式更改和RunPython操作組合到同一個遷移中,否則您可能會遇到像OperationalError一樣的錯誤:無法更改TABLE「mytable」,因爲它具有掛起的觸發器事件。 –

75

另一個原因可能是因爲您嘗試將列設置爲NOT NULL,但實際上它已具有NULL值。

+1

這是巨大的!這次真是萬分感謝。 –

+2

要解決此問題,您可以使用數據遷移或手動(manage.py shell)進入並更新不符合的值 – mgojohn

+0

@mgojohn您如何執行此操作? – pyramidface

相關問題