Betrachte das folgende Skelett einer models.py für ein Weltraum-Eroberungsspiel:
%Vor%Ich habe viele solcher Datenmodelle für ein Projekt, an dem ich gerade arbeite, und ich ändere den Zustand des Spiels aufgrund einiger komplizierter Interaktionen zwischen verschiedenen Datenobjekten. Ich möchte viele unnötige Aufrufe an die Datenbank vermeiden, also mache ich einmal pro Runde etwas wie
Dieses Modell scheint bei der Verwendung von ForeignKey-Objekten vollständig zu zerfallen. Zum Beispiel, wenn eine neue Flotte einen Planeten verlässt, habe ich eine Linie, die ungefähr so aussieht:
%Vor%Nachdem diese Zeile ausgeführt wurde, habe ich einen anderen Code, der die Anzahl der Schiffe auf jedem der Planeten ändert, einschließlich der Planetenflotte. Leider spiegeln sich die Änderungen in der obigen Zeile nicht in dem QuerySet der Planeten, die ich früher erhalten habe, so dass, wenn ich alle Planeten am Ende des Zuges speichere, die Änderungen an den Schiffen von fleet.home überschrieben werden.
>Gibt es einen besseren Weg, um mit dieser Situation umzugehen? Oder sind alle ORMs so?
Djangos ORM implementiert keine Identitätskarte (sie befindet sich im Ticket-Tracker , aber es ist nicht klar, ob und wann es implementiert wird, mindestens ein Django-Kern-Committer hat äußerte sich dagegen ). Wenn Sie also über zwei verschiedene Abfragepfade am gleichen Datenbankobjekt ankommen, arbeiten Sie mit verschiedenen Python-Objekten im Speicher.
Dies bedeutet, dass Ihr Design (Laden Sie alles in den Speicher auf einmal, ändern Sie viele Dinge, und speichern Sie dann alles zurück am Ende) ist nicht mit dem Django ORM funktionieren. Erstens, weil es häufig viel Speicherplatz in doppelte Kopien desselben Objekts lädt, und zweitens wegen "Überschreiben" von Problemen wie dem, in dem Sie gerade laufen.
Entweder müssen Sie Ihr Design überarbeiten, um diese Probleme zu vermeiden (entweder vorsichtig sein, mit jeweils nur einem QuerySet zu arbeiten, alles zu speichern, bevor Sie eine andere Abfrage erstellen, oder wenn Sie mehrere Abfragen laden, alle Relationen manuell nachschlagen, Verwenden Sie niemals die ForeignKeys, die die für sie geeigneten Attribute verwenden, oder verwenden Sie ein alternatives Python-ORM, das eine Identitätszuordnung implementiert. SQLAlchemy ist eine Option.
Beachten Sie, dass dies nicht bedeutet, dass Djangos ORM "schlecht" ist. Es ist optimiert für den Fall von Web-Anwendungen, wo solche Probleme selten sind (Ich habe seit Jahren Web-Entwicklung mit Django gemacht und hatte dieses Problem nie in einem realen Projekt). Wenn Ihr Anwendungsfall anders ist, möchten Sie möglicherweise ein anderes ORM auswählen.
Tags und Links django orm django-models django-orm