Ошибка миграции Django при изменении поля manytomany на внешний ключ

Изначально мой models.py выглядел так:

class P (models.Model):
    first_name=models.CharField(max_length=100);

    def __str__(self):
        return self.first_name

class T (models.Model):
    p_id=models.ManyToManyField(P)

Все отлично работало. затем я изменил класс T, как показано ниже:

class T (models.Model):
        p_id=models.ForeignKey(P,on_delete=models.CASCADE,default=None,null=True)
#I have added default values coz django asks me to during migrations

Я получаю следующую ошибку:

django.db.utils.ProgrammingError: column "p_id_id" does not exist

Раньше, когда возникала такая ошибка, я удалял все таблицы из Postgresql DB, затем закомментировал весь файл models.py в моем приложении, запустил поддельную миграцию, затем раскомментировал models.py и снова запустил миграции, и это сработало. Но это уничтожает все данные в БД. Есть ли способ заставить его работать без удаления данных?

Что, если вы напишете его с двумя миграциями? Сначала удалите m2m, затем выполните миграцию, а затем добавьте ForeignKey и снова выполните миграцию? Более того, логично, что он уничтожает данные: m2m принципиально отличается от внешнего ключа.

Willem Van Onsem 09.09.2018 09:09

Поскольку модель m2m означает, что у одного P может быть ноль, один или несколько T, было бы странно решать эту проблему. Что бы вы сделали, если бы P было несколько?

Willem Van Onsem 09.09.2018 09:09

Я попытался закомментировать m2m и выполнить миграцию, но получил ошибку - django.db.utils.ProgrammingError: столбец «p_id_id» отношения «appname_t» не существует. Я проверил свою текущую базу данных, каждый T имеет уникальный P. 1 T может иметь только 1 P., но 1P может иметь несколько T.

Aseem 09.09.2018 09:16

Это связано с тем, что миграция, которую вы сделали, на самом деле была разрешена частично (да, я знаю, это действительно одна из проблемных частей Django, что, если миграция идет не так, она остается таковой как "частично решенная", и, следовательно, когда вы выполнить миграцию снова, вы больше не сможете вносить изменения, поскольку некоторые изменения уже внесены).

Willem Van Onsem 09.09.2018 09:17

Комментировать поля не следует. Но вам следует написать несколько миграций: сначала добавьте поле FK; затем скопируйте значения из M2M и, наконец, удалите M2M.

Daniel Roseman 09.09.2018 10:00

Django не позволит мне добавить поле FK из класса P, если уже есть поле m2m из класса P. Как я могу преобразовать m2m в FK, не разрушая данные.

Aseem 09.09.2018 19:27
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
324
1

Ответы 1

Ошибка, о которой я говорю в своем вопросе, возможно, потому что я выполнил поддельную миграцию с p_id как FK в models.py, который сообщил Django, что p_id_id уже существует в БД, просто создайте файл миграции. Когда я повторил все с нуля без поддельной миграции, ошибка исчезла.

Django не изменит m2m на FK (от одного ко многим) автоматически, и это имеет смысл. Если я запускаю миграции после изменения m2m на FK, таблица сопоставления appname_t_p удаляется, и данные теряются навсегда. Я сделал следующее, и это сработало:

Резервное копирование таблицы сопоставления, созданной во время m2m "appname_t_p" вручную.

create table atp as select * from appname_t_p;

измените m2m на FK в models.py (как показано в вопросе). затем выполнялись миграции (а не поддельные миграции). Это создало новый столбец p_id_id со всеми значениями NULL в таблице T.

Затем вручную написал оператор обновления sql для добавления значений из указанной выше резервной копии таблицы atp в столбец p_id_id (все NULLS) в таблице appname_t.

UPDATE appname_t t1
SET    p_id_id = t2.p_id
FROM   atp t2
WHERE  t2.t_id = t1.id;

Потом проверил значения, и все было правильно.

Другие вопросы по теме