Как переименовать поле с иностранными ключами в Юг? - PullRequest
13 голосов
/ 15 августа 2010

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

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

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

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

Есть идеи?

Ответы [ 4 ]

24 голосов
/ 21 июля 2011

Во-первых, вам нужно использовать имя столбца БД, а не имя в модели. Например: 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']))
11 голосов
/ 26 июля 2011

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

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

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

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

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

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

6 голосов
/ 24 октября 2010

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

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

А не

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

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

4 голосов
/ 14 марта 2013

Обновление: с 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) взята из автоматически созданных миграций Юга для согласованности.

...