Opened 10 years ago
Closed 6 years ago
#24260 closed New feature (fixed)
Add migration support for logical field renames
Reported by: | Raymond Penners | Owned by: | nobody |
---|---|---|---|
Component: | Migrations | Version: | 1.7 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Suppose you have a legacy model, defined like this:
class Foo(models.Model): foo_id = models.AutoField(primary_key=True)
Now, I would like to clean this up, into:
class Foo(models.Model): id = models.AutoField(primary_key=True, db_column='foo_id')
This is only a logical name change, without any impact on the
database. Yet, there seems to be no way to convince makemigrations
that nothing needs to happen.
Whatever I do, it will always complain, or worse, attempt to remove
the foo_id
altogether:
operations = [ migrations.RemoveField( model_name='foo', name='foo_id', ), migrations.AddField( model_name='foo', name='id', field=models.AutoField(default=0, serialize=False, primary_key=True, db_column=b'foo_id'), preserve_default=False, ), ]
Using South you could work around this by having empty
forwards/backwards methods. It would be nice if Django migrations
offered a way out as well.
Change History (6)
comment:1 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Bug → New feature |
comment:2 by , 10 years ago
Actually, something like simply
migrations.AlterField( model_name='foo', name='id', field=models.AutoField(default=0, serialize=False, primary_key=True, db_column=b'foo_id'), preserve_default=False, )
might work. Did you try that? Django needs a migration to know the field has changed, even if no SQL is generated.
comment:3 by , 10 years ago
That does not seem to help. If I add the following migration:
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations class Migration(migrations.Migration): dependencies = [ ('foo', '0001_initial'), ] operations = [ migrations.AlterField( model_name='foo', name='id', field=models.AutoField(serialize=False, primary_key=True, db_column=b'foo_id'), preserve_default=False, ), ]
Then:
python manage.py makemigrations foo You are trying to add a non-nullable field 'id' to foo without a default; we can't do that (the database needs something to populate existing rows). Please select a fix: 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:
Putting some dummy default=0
or something in the migration does not help either.
comment:4 by , 10 years ago
You should get it working with
operations = [ migrations.AlterField( model_name='foo', name='foo_id', field=models.AutoField(db_column='foo_id', primary_key=True, serialize=False), ), migrations.RenameField( model_name='foo', old_name='foo_id', new_name='id', ), ]
This can be semi-automated by first ensuring the field arguments are explicitly set for foo_id
(foo_id = models.AutoField(primary_key=True, db_column='foo_id')
, then running makemigrations followed by a rename (id = models.AutoField(primary_key=True, db_column='foo_id')
and another makemigrations (the latter will ask if foo.foo_id
is being renamed to foo.id
).
I don't, however, see a way how Django could automatically detect these changes in a single run, given that we have to check for renamed fields first: https://github.com/django/django/blob/master/django/db/migrations/autodetector.py#L183-L186 . After all, we will end up with two operations.
comment:5 by , 8 years ago
Related to #24157 where the autodetector can't detect a rename when the field options are also changed.
comment:6 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I'm pretty confident #29245 was a duplicate that will be fixed in Django 2.1 by 2156565b5bac2e6f503ad4841e2b6ed44e4de656.
I'm guessing you might be able to use the SeparateDatabaseAndState operation to achieve this, but if so, the documentation should really be improved with an example.