Изначально мой 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 означает, что у одного P может быть ноль, один или несколько T, было бы странно решать эту проблему. Что бы вы сделали, если бы P было несколько?
Я попытался закомментировать m2m и выполнить миграцию, но получил ошибку - django.db.utils.ProgrammingError: столбец «p_id_id» отношения «appname_t» не существует. Я проверил свою текущую базу данных, каждый T имеет уникальный P. 1 T может иметь только 1 P., но 1P может иметь несколько T.
Это связано с тем, что миграция, которую вы сделали, на самом деле была разрешена частично (да, я знаю, это действительно одна из проблемных частей Django, что, если миграция идет не так, она остается таковой как "частично решенная", и, следовательно, когда вы выполнить миграцию снова, вы больше не сможете вносить изменения, поскольку некоторые изменения уже внесены).
Комментировать поля не следует. Но вам следует написать несколько миграций: сначала добавьте поле FK; затем скопируйте значения из M2M и, наконец, удалите M2M.
Django не позволит мне добавить поле FK из класса P, если уже есть поле m2m из класса P. Как я могу преобразовать m2m в FK, не разрушая данные.






Ошибка, о которой я говорю в своем вопросе, возможно, потому что я выполнил поддельную миграцию с 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;
Потом проверил значения, и все было правильно.
Что, если вы напишете его с двумя миграциями? Сначала удалите m2m, затем выполните миграцию, а затем добавьте
ForeignKeyи снова выполните миграцию? Более того, логично, что он уничтожает данные: m2m принципиально отличается от внешнего ключа.