177👍
So when I tried this, it seems you can condense Step 3 – 7:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar'),
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
You may get some errors if you don’t update the names where it’s imported e.g. admin.py and even older migration files (!).
Update: As ceasaro mentions, newer versions of Django are usually able to detect and ask if a model is renamed. So try manage.py makemigrations
first and then check the migration file.
47👍
At first, I thought that Fiver’s method worked for me because the migration worked well until step 4. However, the implicit changes ‘ForeignKeyField(Foo)’ into ‘ForeignKeyField(Bar)’ was not related in any migrations. This is why migration failed when I wanted to rename relationship fields (step 5-8).
This might be due to the fact that my ‘AnotherModel’ and ‘YetAnotherModel’ are dispatched in other apps in my case.
So I managed to rename my models and relationship fields doing following below steps:
I adapted the method from this and particularly the trick of otranzer.
So like Fiver let’s say we have in myapp:
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
And in myotherapp:
class AnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Foo)
is_ridonkulous = models.BooleanField()
Step 1:
Transform every OneToOneField(Foo) or ForeignKeyField(Foo) into IntegerField(). (This will keep the id of related Foo object as value of the integerfield).
class AnotherModel(models.Model):
foo = models.IntegerField()
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.IntegerField()
is_ridonkulous = models.BooleanField()
Then
python manage.py makemigrations
python manage.py migrate
Step 2: (Like step 2-4 from Fiver)
Change the model name
class Bar(models.Model): # <-- changed model name
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
Create an empty migration:
python manage.py makemigrations --empty myapp
Then edit it like:
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RenameModel('Foo', 'Bar')
]
Eventually
python manage.py migrate
Step 3:
Transform Back your IntegerField() into their previous ForeignKeyField or OneToOneField but with the new Bar Model. (The previous integerfield was storing the id, so django understand that and reestablish the connection, which is cool.)
class AnotherModel(models.Model):
foo = models.ForeignKey(Bar)
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
foo = models.ForeignKey(Bar)
is_ridonkulous = models.BooleanField()
Then do:
python manage.py makemigrations
Very importantly, at this step you have to modify every new migrations and add the dependency on the RenameModel Foo-> Bar migrations.
So if both AnotherModel and YetAnotherModel are in myotherapp the created migration in myotherapp must look like this:
class Migration(migrations.Migration):
dependencies = [
('myapp', '00XX_the_migration_of_myapp_with_renamemodel_foo_bar'),
('myotherapp', '00xx_the_migration_of_myotherapp_with_integerfield'),
]
operations = [
migrations.AlterField(
model_name='anothermodel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.AlterField(
model_name='yetanothermodel',
name='foo',
field=models.ForeignKey(to='myapp.Bar')
),
]
Then
python manage.py migrate
Step 4:
Eventually you can rename your fields
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) <------- Renamed fields
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) <------- Renamed fields
is_ridonkulous = models.BooleanField()
and then do automatic renaming
python manage.py makemigrations
(django should ask you if you actually renamed the modelname, say yes)
python manage.py migrate
And that’s it!
This works on Django1.8
- [Django]-Resource temporarily unavailable using uwsgi + nginx
- [Django]-Alowing 'fuzzy' translations in django pages?
- [Django]-Create a field whose value is a calculation of other fields' values
32👍
In the current version of Django you can rename the model and run 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.
- [Django]-Django storages aws s3 delete file from model record
- [Django]-What's the idiomatic Python equivalent to Django's 'regroup' template tag?
- [Django]-How to filter empty or NULL names in a QuerySet?
10👍
I needed to do the same thing and follow. I changed the model all at once (Steps 1 and 5 together from Fiver’s answer). Then created a schema migration but edited it to be this:
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('Foo','Bar')
def backwards(self, orm):
db.rename_table('Bar','Foo')
This worked perfectly. All my existing data showed up, all the other tables referenced Bar fine.
from here: https://hanmir.wordpress.com/2012/08/30/rename-model-django-south-migration/
- [Django]-Setting DEBUG = False causes 500 Error
- [Django]-How to perform OR condition in django queryset?
- [Django]-Django order_by query set, ascending and descending
8👍
For Django 1.10, I managed to change two model class names (including a ForeignKey, and with data) by simply running Makemigrations, and then Migrate for the app. For the Makemigrations step, I had to confirm that I wanted to change the table names. Migrate changed the names of the tables without a problem.
Then I changed the name of the ForeignKey field to match, and again was asked by Makemigrations to confirm that I wanted to change the name. Migrate than made the change.
So I took this in two steps without any special file editing. I did get errors at first because I forgot to change the admin.py file, as mentioned by @wasibigeek.
- [Django]-Access web server on VirtualBox/Vagrant machine from host browser?
- [Django]-Django create userprofile if does not exist
- [Django]-Django template can't see CSS files
6👍
I also faced the problem as v.thorey described and found that his approach is very useful but can be condensed into fewer steps which are actually step 5 to 8 as Fiver described without step 1 to 4 except that step 7 needs to be changed as my below step 3. The overall steps are as follow:
Step 1: Edit the related field names in models.py
class Bar(models.Model):
name = models.CharField(unique=True, max_length=32)
description = models.TextField(null=True, blank=True)
class AnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_awesome = models.BooleanField()
class YetAnotherModel(models.Model):
bar = models.ForeignKey(Bar) # <-- changed field name
is_ridonkulous = models.BooleanField()
Step 2: Create an empty migration
python manage.py makemigrations --empty myapp
Step 3: Edit the Migration class in the migration file created in Step 2
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='AnotherModel',
name='foo',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='YetAnotherModel',
name='foo',
field=models.IntegerField(),
),
migrations.RenameModel('Foo', 'Bar'),
migrations.AlterField(
model_name='AnotherModel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.AlterField(
model_name='YetAnotherModel',
name='foo',
field=models.ForeignKey(to='myapp.Bar'),
),
migrations.RenameField('AnotherModel', 'foo', 'bar'),
migrations.RenameField('YetAnotherModel', 'foo', 'bar')
]
Step 4: Apply the migration
python manage.py migrate
Done
P.S. I’ve tried this approach on Django 1.9
- [Django]-Update all models at once in Django
- [Django]-Django render_to_string missing information
- [Django]-Warning: Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'
6👍
Just wanted to confirm and add upon ceasaro comment. Django 2.0 seems to do this automatically now.
I’m on Django 2.2.1, all I had to do what to rename the model and run makemigrations
.
Here it asks if I had renamed the specific class from A
to B
, i chose yes and ran migrate and all seems to work.
Note I did not rename the old model name in any files inside the project/migrations folder.
- [Django]-Get Timezone from City in Python/Django
- [Django]-How to debug in Django, the good way?
- [Django]-Django form: what is the best way to modify posted data before validating?
5👍
I am using Django version 1.9.4
I have follow the following steps:-
I have just rename the model oldName to NewName
Run python manage.py makemigrations
. It will ask you for
Did you rename the appname.oldName model to NewName? [y/N]
select Y
Run python manage.py migrate
and it will ask you for
The following content types are stale and need to be deleted:
appname | oldName
appname | NewName
Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you’re unsure, answer ‘no’.
Type 'yes' to continue, or 'no' to cancel: Select No
It rename and migrate all existing data to new named table for me.
- [Django]-How to convert a Django QuerySet to a list?
- [Django]-How to solve "Page not found (404)" error in Django?
- [Django]-Django select_for_update cannot be used outside of a transaction
3👍
Unfortunately, I found problems (each django 1.x) with rename migration which leave old table names in the database.
Django doesn’t even try anything on the old table, just rename his own model.
The same problem with foreign keys, and indices in general – changes there are not tracked properly by Django.
The simplest solution (workaround):
class Foo(models.Model):
name = models.CharField(unique=True, max_length=32)
...
Bar = Foo # and use Bar only
The real solution (an easy way to switch all
indices, constraints, triggers, names, etc in 2 commits, but rather for smaller tables):
commit A:
- create the same model as the old one
# deprecated - TODO: TO BE REMOVED
class Foo(model.Model):
...
class Bar(model.Model):
...
- switch code to work with new model
Bar
only.
(including all relations on the schema)
In migration prepare RunPython
, which copy data from Foo to Bar
(including id
of Foo)
- optional optimization (if needed for greater tables)
commit B: (no rush, do it when an entire team is migrated)
- safe drop of the old model
Foo
further cleanup:
- squash on migrations
bug in Django:
- [Django]-How to test auto_now_add in django
- [Django]-Django, Models & Forms: replace "This field is required" message
- [Django]-Django – SQL bulk get_or_create possible?
1👍
I needed to rename a couple of tables. But only one model rename was noticed by Django. That happened because Django iterates over added, then removed models. For each pair it checks if they’re of the same app and have identical fields. Only one table had no foreign keys to tables to be renamed (foreign keys contain model class name, as you remember). In other words, only one table had no field changes. That’s why it was noticed.
So, the solution is to rename one table at a time, changing model class name in models.py
, possibly views.py
, and making a migration. After that inspect your code for other references (model class names, related (query) names, variable names). Make a migration, if needed. Then, optionally combine all these migrations into one (make sure to copy imports as well).
- [Django]-How to change empty_label for modelForm choice field?
- [Django]-Default filter in Django model
- [Django]-Django-taggit – how do I display the tags related to each record
1👍
I would make @ceasaro words, mine on his comment on this answer.
Newer versions of Django can detect changes and ask about what was done.
I also would add that Django might mix the order of execution of some migration commands.
It would be wise to apply small changes and run makemigrations
and migrate
and if the error occurs the migration file can be edited.
Some lines order of execution can be changed to avoid erros.
- [Django]-Get the list of checkbox post in django views
- [Django]-Determine variable type within django template
- [Django]-Django Template Language: Using a for loop with else
1👍
2023 update:
- Rename model Foo->Bar
- Run
makemigrations
- Rename fields in related models foo->bar
- Run
makemigrations
- Migrate & enjoy
If you rename a model and related fields at the same time, instead of renaming old model will be deleted and a new one created
- [Django]-Cannot set Django to work with smtp.gmail.com
- [Django]-NumPy array is not JSON serializable
- [Django]-Django: Arbitrary number of unnamed urls.py parameters
0👍
If you are using a good IDE like PyCharm you can right click on the model name and do a refactor -> rename. This saves you the trouble of going through all your code that references the model. Then run makemigrations and migrate. Django 2+ will simply confirm name change.
- [Django]-Timestamp fields in django
- [Django]-How to customize activate_url on django-allauth?
- [Django]-Multiple Database Config in Django 1.2
-14👍
I upgraded Django from version 10 to version 11:
sudo pip install -U Django
(-U
for “upgrade”) and it solved the problem.
- [Django]-Http POST drops port in URL
- [Django]-Django Form File Field disappears on form error
- [Django]-Sending post data from angularjs to django as JSON and not as raw content