Как переименовать поле foreignkey с South?

Переименование простого charfield и т.д. кажется легким (Django - как переименовать поле модели с помощью юга?)

Однако, когда я пытаюсь использовать то же самое в поле ForeignKey, я получаю сообщение об ошибке:

_mysql_exceptions.OperationalError: (1091, "Can't DROP '[new_fkey_field_name]'; check that column/key exists")

Это связано с миграцией, которая пытается по какой-то причине запустить обратную связь (как показано на трассе).

Любые идеи?

Ответы

Ответ 1

Обновление: с помощью mysql-5.5.30-1.fc18.x86_64 и

MySQL-python==1.2.4
Django==1.4.2
South==0.7.6

выполняются следующие работы:

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']
                        ))

Как комментарии @Eloff, Юг не может найти оригинальный FK по неизвестным причинам, но это, похоже, не имеет значения. Нет необходимости в миграции данных (я считаю), поскольку значения pk не должны меняться.

Спецификация поля (используя self.gf) берется из южных автогенерированных миграций для согласованности.

Ответ 2

Во-первых, вам нужно использовать имя столбца db, а не имя модели. Например: foobar_id не foobar.

Затем вам нужно отбросить ограничения fk и воссоздать их после переименования:

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']))

Если ваш fk является нулевым, вам нужно использовать его для изменения:

db.alter_column('app_model', 'new_id', models.ForeignKey(null=True, to=orm['app.OtherModel']))

Ответ 3

Пользователи MySQL должны знать об этой ошибке на юге, если она действительно применяется:

http://south.aeracode.org/ticket/697

Обходной путь состоит в том, чтобы выполнить миграцию в 3 этапа:

1) Добавить новое поле

2) данные переносят данные в новое поле

3) удалите старое поле

Ответ 4

При переименовании ForeignKey не забудьте добавить _id в конец имени поля, которое вы используете в Django. Например.

db.rename_column('accounts_transaction', 'operator_id', 'responsible_id')

И не

db.rename_column('accounts_transaction', 'operator', 'responsible')

Но я тестировал это только на sqlite (на самом деле у меня вообще нет ALTER_TABLE), поэтому я не знаю, действительно ли это будет работать с mysql/postgres.