Я думаю, что у меня есть довольно туманный случай, который Джанго не освещает.Я использую Django 1.11.20, и эта проблема возникает при использовании mySQL, с sqlite проблем нет (так как здесь не используются ограничения на использование внешних ключей)
Итак, вот настройки.
- У меня есть модель с именем 'Function', и у нее есть поле автоматического первичного ключа 'id' (сделано Django)
У меня есть модель с именем 'Training' ичто существует отношение ManyToMany, называемое «subscribe_functions», которое указывает на функцию.
class Training(RegistrationBlock):
subscribe_functions = models.ManyToManyField('Function', blank=False, limit_choices_to={'avail_option': True},
related_name="trainings",
verbose_name=_('Functiongroups that may register'),
help_text=_('People in the selected functions may register their '
'availability'))
Таким образом, Django создал хорошую промежуточную таблицу для этого и нав этой таблице есть ограничение внешнего ключа, которое столбец 'function_id' указывает на Function.id.
И вот проблема.
Теперь я хочу добавить родителямодель для функции без потери данных и фактически переместить некоторые данные в родительский.Поэтому я делаю родительскую модель ('CoreFunction') и переносу ее (она находится в отдельном приложении), а затем в своей миграции для функции я делаю следующее:
переименование поля 'id 'on Function в' corefunction_ptr '
migrations.RenameField(
model_name='function',
old_name='id',
new_name='corefunction_ptr'
),
Передать некоторые данные из дочерней модели в родительскую модель с помощью операции RunPython
и затем сделайте следующее:
migrations.AlterField(
model_name='function',
name='corefunction_ptr',
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='rlgcore.CoreFunction'),
),
По существу, превращение поля corefunction_ptr в поле primary_key и указание его на родительскую модель.
При запуске этой миграции на mySQLБаза данных Я получаю сообщение об ошибке, что существует ограничение внешнего ключа и что поле corefunction_ptr не может быть изменено.
_mysql_exceptions.OperationalError: (1846, 'ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE.')
Копая в моей базе данных, я обнаружил, что это ограничение для промежуточной таблицы training_subscribeefunctions .
Я точно определил его в этом запросе (который выдает ту же ошибку при выдаче в phpmyadmin).ALTER TABLE 'pe_function' CHANGE 'corefunction_ptr' 'corefunction_ptr_id' integer NOT NULL;
Однако была другая модель, связанная с Function через ForeignKey, и для этой таблицы ограничение было удалено и позже будет создано заново.(Я запустил python manage.py sqlmigrate [appname] [migrationname
], чтобы посмотреть, что происходит)
Я нашел код в Django , где принимается решение о том, следует ли снять ограничение на использование внешней клавиши, но поскольку оно определено длябыть обратным, если многие решения могут привести к ложному ответу.
Таким образом, вопрос заключается в
Как я могу написать код в моем файле миграции, чтобы проверить, есть ли другие ограничениямодель, для которой я пытаюсь переименовать поле идентификатора, затем сбросить ограничение и позже добавить его снова?
Я нашел способ найти ограничения, указывающие на таблицу через сырой SQLзапрос.Однако я должен был бы хранить всю найденную информацию где-нибудь (глобальные переменные?), Чтобы иметь возможность добавить то же ограничение позже.Я бы предпочел использовать сам код Django (например, из BaseDatabaseSchemaEditor._alter_field ), но я не знаю как.
Я знаю, что функции, которые вы можете передать в RunPython
операция получения schema_editor, но я не знаю, как / где получить и как передать параметры _delete_constraint_sql
и _create_fk_sql
ожидают.
Я бы хотел исправить это с помощью небольшого жесткого кодированияполя / имена таблиц / названия моделей и т. д. насколько возможно.
Есть мысли?