I'm having issues with reverting a Django (1.8.7) migration that contains the renaming of a table. Even though it seems to be able to rename it in Postgres, it then tries to add a constraint using the old table name.
Here's the traceback:
cursor.execute(sql, params)
File "/Users/myworkspace/projects/xxx/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/Users/myworkspace/projects/xxx/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/myworkspace/projects/xxx/venv/lib/python3.5/site-packages/django/db/utils.py", line 97, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/myworkspace/projects/xxx/venv/lib/python3.5/site-packages/django/utils/six.py", line 658, in reraise
raise value.with_traceback(tb)
File "/Users/myworkspace/projects/xxx/venv/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "team_membershiprole" does not exist
If you take a look at the SQL it generates,
[...]
ALTER TABLE "team_membershiprole" RENAME TO "team_leadershiprole";
[...]
ALTER TABLE "team_leadershipteammember"
ADD CONSTRAINT "team_l_role_id_xxx"
FOREIGN KEY ("role_id") REFERENCES "team_membershiprole" ("id")
DEFERRABLE INITIALLY DEFERRED;
[...]
COMMIT;
You can see that there's a reference to team_membershiprole
, even though that table doesn't exist anymore (it was renamed). Here's the migration code:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0023_xxx'),
('team', '0009_xxx2'),
]
operations = [
migrations.CreateModel(
name='TeamMembership',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('team', models.ForeignKey(related_name='members', to='team.Team')),
('member', models.ForeignKey(to='core.Member')),
],
),
migrations.RenameModel(
old_name='LeadershipRole',
new_name='MembershipRole',
),
migrations.RemoveField(
model_name='leadershipteammember',
name='team',
),
migrations.RemoveField(
model_name='leadershipteammember',
name='member',
),
migrations.RemoveField(
model_name='leadershipteammember',
name='role',
),
migrations.DeleteModel(
name='LeadershipTeamMember',
),
migrations.AddField(
model_name='teammembership',
name='role',
field=models.ForeignKey(to='team.MembershipRole'),
),
]
I understand this is might be a Django migrations bug, but is there any way to work around it?
If it's a brand new migration, 2 and 3 won't apply, and it's perfectly fine to rename them.
You can override Migration.unapply so it uses a different set of operations.
class MyMigration(Migration):
operations = [
... your operations ...
]
reverse_operations = [
... your fixed reverse operations ...
]
def unapply(self, project_state, schema_editor, collect_sql=False):
self.operations = self.reverse_operations
return super(MyMigration, self).unapply(..)
I have not tested this but it should give you an idea. Oh and you might need to reverse the list of reverse migrations because Django will be expecting it to be the list of forward migrations so traverse them in reverse.
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