2015-07-19 112 views
13

所以有的時候一對夫婦遷移後,我的第一次,我決定我要包括以下字段:Django 1.8遷移。創建數據庫後添加DateTimeField。最佳實踐?

created = models.DateTimeField(auto_now_add=True) 
modified = models.DateTimeField(auto_now=True) 

到我的車型之一。當我makemigrations它給了我 You are trying to add a non-nullable field 'created' to episode without a default; we can't do that (the database needs something to populate existing rows).

所以我當時把它改爲

created = models.DateTimeField(auto_now_add=True, default=datetime.now) 

試圖再次makemigrations後,說at_api.Episode.modified: (fields.E160) The options auto_now, auto_now_add, and default are mutually exclusive. Only one of these options may be present.

好,所以我就繼續和刪除auto_now_add

created = models.DateTimeField(default=datetime.now) 

我現在可以makemigrations沒有任何問題。然後我刪除了default=datetime.now,並用auto_now_add=True替換它,然後再次遷移,沒有任何問題。然而,我不禁覺得這可能不是做事的最佳方式。我覺得項目後期可能會出現問題。

回答

7

我認爲這裏的最佳做法是使這些字段可以爲空。目前您的created字段的含義是:「實例創建時的時間,當我運行遷移的任意時間。」表示缺少值的標準方式是NULL,而不是任意值。這就是說,如果你想要使用一些任意的值,你只需要告訴Django它是什麼。通常makemigrations爲您提供了指示用於現有行的一次性值的選項 - 這是否發生?

更麻煩的方法是聲明域爲空,然後創建數據遷移以填充所需的值,然後使其不可空。你所做的基本上是一個簡化版本。除了created這個問題不是真正創建實例的時候,我不認爲它帶來了任何問題。

+0

是的,django的確問我現有行的一次性價值。我試過'datetime.now',但它似乎沒有工作。但是我認爲一切都很好呢?對於現有的行值,將「null = True」設置爲「佔位符」是否典型,然後稍後將其刪除以替換其他值? – pyramidface

+0

'datetime.now()'本來有效(注意圓括號 - 你想調用函數並使用它的返回值)。在需要爲不同行分配不同值的更復雜情況下,您可以添加和刪除'null = True'。例如,假設您將實際創建日期存儲在某個文件中。你會寫一個數據遷移,爲每一行查找文件中的日期,然後將其放入數據庫中。之後,您可以刪除'null = True'並再次遷移。 –

+0

啊,好吧,我會在未來的項目中記住這一點。謝謝!! – pyramidface

1

我剛剛遇到了確切的問題。我使用Django 1.10。我讀凱文的答案,我試圖把默認值,當Django要求我填寫它作爲datetime.now字符串。 我很驚訝,因爲,這些字段,Django的,如果你想使用datetime.now默認自動問你:

$ ./manage.py makemigrations 
You are trying to add the field 'date_created' with 'auto_now_add=True' to projectasset without a default; the database needs something to populate existing rows. 

1) Provide a one-off default now (will be set on all existing rows) 
2) Quit, and let me add a default in models.py 
Select an option: 1 
Please enter the default value now, as valid Python 
You can accept the default 'timezone.now' by pressing 'Enter' or you can provide another value. 
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now 
Type 'exit' to exit this prompt 
[default: timezone.now] >>> 

所以,我只是確認,一切似乎是工作的罰款!