I have a django project with a database table that already contains data. I'd like to change the field name without losing any of the data in that column. My original plan was to simply change the model field name in a way that would not actually alter the name of the db table (using the db_column
column parameter):
The original model:
class Foo(models.Model): orig_name = models.CharField(max_length=50)
The new model:
class Foo(models.Model): name = models.CharField(max_length=50, db_column='orig_name')
But, running South's schemamigration --auto
produces a migration script that deletes the original column, orig_name
, and adds a new column, name
, which would have the unwanted side effect of deleting the data in that column. (I'm also confused as to why South wants to change the name of the column in the db, since my understanding of db_column was that it enables a change to the model field name without changing the name of the database table column).
If I can't get away with changing the model field without changing the db field, I guess I could do a more straight forward name change like so:
The original model:
class Foo(models.Model): orig_name = models.CharField(max_length=50)
The new model:
class Foo(models.Model): name = models.CharField(max_length=50)
Regardless of which strategy I end up using (I would prefer the first, but would find the second acceptable), my primary concern is ensuring that I don't lose the data that is already in that column.
Does this require a multi-step process? (such as 1. adding a column, 2. migrating the data from the old column to the new column, and 3. removing the original column) Or can I alter the migration script with something like db.alter_column
?
What is the best way to preserve the data in that column while changing the column's name?
To rename a model and relationship fields with Python Django migrations, we can use the RenameModel and RenameField methods. to create the Migration migration class that has the operations list. We call RenameModel to rename a model field's name from Foo to Bar .
Show activity on this post. This way a new migration file will be created. Set your column details there, run the migrations using php artisan migrate and that's all. You'll have this new column in your users table without losing previously stored data.
In the current version of Django you can rename the model and run the python manage.py makemigrations , django will then ask if you want to rename the model and if you select yes, then all renaming process will be done automatically.
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.
Adding an answer for Django 1.8+ (with Django-native migrations, rather than South).
Make a migration that first adds a db_column
property, and then renames the field. Django understands that the first is a no-op (because it changes the db_column
to stay the same), and that the second is a no-op (because it makes no schema changes). I actually examined the log to see that there were no schema changes...
operations = [ migrations.AlterField( model_name='mymodel', name='oldname', field=models.BooleanField(default=False, db_column=b'oldname'), ), migrations.RenameField( model_name='mymodel', old_name='oldname', new_name='newname', ), ]
Django 2.0.9 (and onwards) can automatically detect if a field was renamed and gives an option to rename instead of delete and create a new one
(same works for Django 2.2)
Initial answer
Posting, if it's still helpful for someone.
For Django 2.0 + simply rename the field in the model
class Foo(models.Model): orig_name = models.CharField(max_length=50)
to
class Foo(models.Model): name = models.CharField(max_length=50)
Now run python manage.py makemigrations
It'll generate migration with operations for removing the old field and adding the new one.
Go ahead and change that to following.
operations = [ migrations.RenameField( model_name='foo', old_name='orig_name', new_name='name') ]
Now run python manage.py migrate
it'll rename the column in DB without losing data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With