У меня есть устаревшая модель Django, которая немного специфична в своем исполнении для моих вкусов. Я хочу создать более конкретные подклассы этой модели для обработки различных сценариев, но хочу сохранить общий базовый класс для некоторых общих полей и методов. Пример модели выглядит следующим образом:
class SomeOldClass(models.Model):
sharedField1 = models.CharField('This is a shared field1', max_length=10)
sharedField2 = models.CharField('This is a shared field2', max_length=10)
specificField1 = models.CharField('This is a specific field1', max_length=10)
В конечном итоге я пытаюсь выделить подкласс SomeOldClass, который разделяет sharedField1 и sharedField2.
class SomeOldSubclass(SomeOldClass):
specificField1_new = models.CharField('This is a specific field1', max_length=10)
Обратите внимание на _new, добавленный к specificField1 в SomeOldSubclass из-за ошибок при создании поля с тем же именем, что и у родителя.
Мой план - три южных сценария:
- Схема миграции для создания нового
таблица app_someoldsubclass
- Данные
сценарий миграции для копирования значений из
app_someoldclass.specificField1 to
app_someoldsubclass.specificField1_new
- миграция схемы для удаления
specificField1 из app_someoldclass
и переименуйте specificField1_new в
specificField1 в
app_someoldsubclass
Конечно, я мог бы объединить эти сценарии в один сценарий миграции, но потерпите меня.
Используя классы, определенные выше, я создал скрипт миграции схемы: ./manage.py schemamigration app --auto
Затем я создал сценарий переноса данных empy: ./manage.py datamigration app copy_values
Я изменил скрипт переноса данных, добавив его в свой метод пересылки:
def forwards(self, orm):
"Write your forwards methods here."
for soc in orm.SomeOldClass.objects.all():
sosc = orm.SomeOldSubclass.objects.get_or_create(someoldclass_ptr=soc, specificField_new=soc.specificField1)
Обратите внимание: поскольку SomeOldSubclass наследуется от SomeOldClass, я создаю новый экземпляр SomeOldSubclass для каждого экземпляра SomeOldClass и обновляю значения someoldclass_ptr и specificField1_new.
Запуск миграций создает новую строку в app_someoldsubclass для каждой строки в app_someoldclass, как и ожидалось, со значением specificField1_new, равным значению в app_someoldclass.specificField1. Но теперь все поля в app_someoldclass полностью уничтожены. Если бы я создал экземпляр модели SomeOldClass для существующего идентификатора, sharedField1
было бы None
. Фактически, единственное значение, которое все еще допустимо, - это идентификатор в app_someoldclass.
Фактически, единственный способ для app_someoldclass сохранить свои исходные значения - это изменить мой метод forward следующим образом:
def forwards(self, orm):
"Write your forwards methods here."
for soc in orm.SomeOldClass.objects.all():
sosc = orm.SomeOldSubclass.objects.get_or_create(someoldclass_ptr=soc, specificField_new=soc.specificField1)
soc.save()
(обратите внимание на добавление soc.save () )
Это ожидаемое поведение? Я бы предположил, что, поскольку я не изменяю свои экземпляры SomeOldClass, представленные объектом soc, не было бы необходимости сохранять его снова. И даже если бы я не сохранил его, я бы точно не ожидал, что данные будут засорены.
Это юг? Джанго вещь? Ошибка пользователя?