2015-07-19 144 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] >>> 

所以,我只是确认,一切似乎是工作的罚款!