Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django 1.8 Migrations. Adding DateTimeField after db creation. Best practices?

So some time a couple migrations after my first one, I decided I wanted to include these fields:

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

into one of my models. When I makemigrations it gave me 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).

So I then changed it to

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

After trying to makemigrations again, it said that 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.

All right, so I just went ahead and removed the auto_now_add

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

I could now makemigrations without any problems. And then I later removed default=datetime.now and replaced it with auto_now_add=True, and migrated again without any problems. However, I can't help feeling that this might not be the best way of doing things. I feel like something might go wrong later in the project.

like image 401
pyramidface Avatar asked Jul 19 '15 07:07

pyramidface


People also ask

How do you add a new field to a model with new Django migrations?

To answer your question, with the new migration introduced in Django 1.7, in order to add a new field to a model you can simply add that field to your model and initialize migrations with ./manage.py makemigrations and then run ./manage.py migrate and the new field will be added to your DB. Save this answer.

How do I fix migration issues in Django?

you can either: temporarily remove your migration, execute python manage.py migrate, add again your migration and re-execute python manage.py migrate. Use this case if the migrations refer to different models and you want different migration files for each one of them.

How do you force migrations to a DB if some tables already exist in Django?

Move the already done migrations from that file into the empty migration you created.. then --fake that one. This will put Django's understanding of what the database looks like will be in sync with reality and you can then migrate as normal, applying the changes in the last migration file.

Does Django migrate create database?

Since version 1.7, Django has come with built-in support for database migrations. In Django, database migrations usually go hand in hand with models: whenever you code up a new model, you also generate a migration to create the necessary table in the database. However, migrations can do much more.


1 Answers

I think the best practice here would have been to make the fields nullable. What your created field means at the moment is: "The time when the instance was created, or the arbitrary time when I ran the migration." The standard way to represent the lack of a value is NULL, rather than an arbitrary value.

That said, if you do want to use some arbitrary value you just need to tell Django what it is. Usually makemigrations gives you the option to indicate a one-off value to use for existing rows - did that not happen?

A more laborious method would be to declare the field nullable, then create a data migration to fill in your desired value, and then make it non-nullable. What you did is basically a simplified version of that. I don't see it creating any problems moving forward other than the issue of created not really being the time the instance was created.

like image 109
Kevin Christopher Henry Avatar answered Oct 06 '22 00:10

Kevin Christopher Henry