Ich habe eine Legacy-Django-Modell, das ein wenig zu spezifisch in seiner Umsetzung für meinen Geschmack ist. Ich möchte spezifischere Unterklassen dieses Modells erstellen, um verschiedene Szenarien zu behandeln, aber eine gemeinsame Basisklasse für einige gemeinsame Felder und Methoden beibehalten. Das Beispielmodell ist wie folgt:
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)
Letztlich versuche ich, eine Unterklasse von SomeOldClass zu erstellen, die sharedField1 und sharedField2 gemeinsam nutzt.
class SomeOldSubclass(SomeOldClass):
specificField1_new = models.CharField('This is a specific field1', max_length=10)
Beachten Sie das _new, das an das specificField1 in SomeOldSubclass angehängt wurde, um Fehler beim Erstellen eines Feldes mit demselben Namen wie ein übergeordnetes Feld zu vermeiden.
Mein Plan ist es, drei Süd-Skripte zu haben:
- Schemamigration zur Erstellung des neuen app_someoldsubclass-Tabelle
- Daten Migrationsskript zum Kopieren von Werten aus app_someoldclass.specificField1 nach app_someoldsubclass.specificField1_new
- Schemamigration nach unten specificField1 aus app_someoldclass und Umbenennung von specificField1_new in specificField1 in app_someoldsubclass
Natürlich könnte ich diese Skripte in einem Migrationsskript zusammenfassen, aber ich bitte um Nachsicht.
Mit den oben definierten Klassen habe ich ein Skript zur Schemamigration erstellt: ./manage.py schemamigration app --auto
Dann habe ich ein Skript für die Datenmigration mit Leerzeichen erstellt: ./manage.py datamigration app copy_values
Ich habe das Skript für die Datenmigration geändert, um dies in meine Vorwärtsmethode aufzunehmen:
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)
Da SomeOldSubclass von SomeOldClass erbt, erstelle ich für jede Instanz von SomeOldClass eine neue SomeOldSubclass-Instanz und aktualisiere die Werte someoldclass_ptr und specificField1_new.
Beim Ausführen der Migrationen wird wie erwartet für jede Zeile in app_someoldclass eine neue Zeile in app_someoldsubclass erstellt, wobei der Wert von specificField1_new mit dem Wert in app_someoldclass.specificField1 übereinstimmt. Aber jetzt sind alle Felder in app_someoldclass komplett ausgelöscht. Wenn ich eine Instanz des SomeOldClass-Modells für eine vorhandene id, sharedField1
wäre None
. Tatsächlich ist der einzige Wert, der noch gültig ist, die ID in app_someoldclass.
Die einzige Möglichkeit, die ursprünglichen Werte von app_someoldclass beizubehalten, besteht darin, meine Vorwärtsmethode wie folgt zu ändern:
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()
(Anmerkung: Hinzufügung von soc.save() )
Ist dieses Verhalten zu erwarten? Ich würde davon ausgehen, dass, da ich meine Instanzen von SomeOldClass, wie sie durch das soc-Objekt dargestellt werden, nicht ändere, es nicht notwendig wäre, sie erneut zu speichern. Und selbst wenn ich es nicht speichern würde, würde ich sicher nicht erwarten, dass die Daten verloren gehen.
Ist das eine Sache des Südens? Eine Django-Sache? Eine Sache der Benutzerfehler?