问题
Renaming a simple charfield etc seems easy (Django - How to rename a model field using South?)
However when I try using the same on a ForeignKey field I get an error:
_mysql_exceptions.OperationalError: (1091, "Can't DROP '[new_fkey_field_name]'; check that column/key exists")
Which stems from the migration trying to run the backwards for some reason (as evidenced in the trace).
Any ideas?
回答1:
Update: with mysql-5.5.30-1.fc18.x86_64
and
MySQL-python==1.2.4
Django==1.4.2
South==0.7.6
the following works:
class Migration(SchemaMigration_:
def forwards(self, orm):
db.rename_column('app_model', 'old_id', 'new_id')
db.alter_column('app_model', 'new_id',
self.gf('django.db.models.fields.related.ForeignKey')(
blank=True,
null=True,
to=orm['app.OtherModel']
))
def backwards(self, orm):
db.rename_column('app_model', 'new_id', 'old_id')
db.alter_column('app_model', 'old_id',
self.gf('django.db.models.fields.related.ForeignKey')(
blank=True,
null=True,
to=orm['app.OtherModel']
))
As @Eloff comments, South can't find the original FK for reasons unknown, but it doesn't seem to matter. There is no need for a data migration (I believe) as pk values should not change.
The field specification (using self.gf
) is taken from South's auto-generated migrations for consistency.
回答2:
First, you need to use the db column name not the one in the model. Eg: foobar_id not foobar.
Then you need to drop the fk constraints and recreate them after renaming:
db.drop_foreign_key('app_model', 'old_id')
db.rename_column('app_model', 'old_id', 'new_id')
db.alter_column('app_model', 'new_id', models.ForeignKey(to=orm['app.OtherModel']))
If your fk is nullable you need to use change it to:
db.alter_column('app_model', 'new_id', models.ForeignKey(null=True, to=orm['app.OtherModel']))
回答3:
MySQL users ought to be aware of this bug in south, if indeed it still applies:
http://south.aeracode.org/ticket/697
The workaround is to conduct the migration in 3 steps:
1) Add new field
2) data migrate the data to the new field
3) delete the old field
回答4:
When renaming a ForeignKey
, remember to add _id
to the end of the field name you use in Django. E.g.
db.rename_column('accounts_transaction', 'operator_id', 'responsible_id')
And not
db.rename_column('accounts_transaction', 'operator', 'responsible')
But I have only tested this on sqlite (which don't actually have the ALTER_TABLE at all), so I don't know if it will actually work on mysql/postgres.
来源:https://stackoverflow.com/questions/3485176/how-to-rename-a-foreignkey-field-with-south