How to rename a foreignkey field with South?

旧街凉风 提交于 2019-12-22 02:03:25

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!