Foo.objects.get(pk="foo")
<Foo: test>
In der Datenbank möchte ich ein weiteres Objekt hinzufügen, das eine Kopie des obigen Objekts ist.
Angenommen, meine Tabelle hat eine Zeile. Ich möchte das erste Zeilenobjekt mit einem anderen Primärschlüssel in eine andere Zeile einfügen. Wie kann ich das machen?
python
django
django-models
user426795
quelle
quelle
obj.pk
undobj.id
diese Arbeit in Django 1.4Die Django-Dokumentation für Datenbankabfragen enthält einen Abschnitt zum Kopieren von Modellinstanzen . Angenommen, Ihre Primärschlüssel werden automatisch generiert, erhalten Sie das Objekt, das Sie kopieren möchten, setzen den Primärschlüssel auf
None
und speichern das Objekt erneut:In diesem Snippet erstellt das erste
save()
das Originalobjekt und das zweitesave()
die Kopie.Wenn Sie die Dokumentation weiterlesen, finden Sie auch Beispiele für die Behandlung von zwei komplexeren Fällen: (1) Kopieren eines Objekts, das eine Instanz einer Modellunterklasse ist, und (2) Kopieren verwandter Objekte, einschließlich Objekte in vielen Fällen -Viele Beziehungen.
Hinweis zur Antwort von miah: Das Setzen des pk auf
None
wird in der Antwort von miah erwähnt, obwohl es nicht vorne und in der Mitte dargestellt wird. Meine Antwort dient also hauptsächlich dazu, diese Methode als die von Django empfohlene Methode zu betonen.Historischer Hinweis: Dies wurde in den Django-Dokumenten erst in Version 1.4 erklärt. Dies ist jedoch seit vor 1.4 möglich.
Mögliche zukünftige Funktionalität: Die oben genannten Dokumentänderungen wurden in diesem Ticket vorgenommen . Im Kommentarthread des Tickets gab es auch einige Diskussionen über das Hinzufügen einer integrierten
copy
Funktion für Modellklassen, aber soweit ich weiß, haben sie beschlossen, dieses Problem noch nicht anzugehen. Diese "manuelle" Art des Kopierens muss also wahrscheinlich erst einmal reichen.quelle
Sei hier vorsichtig. Dies kann extrem teuer sein, wenn Sie sich in einer Schleife befinden und Objekte einzeln abrufen. Wenn Sie die Datenbank nicht aufrufen möchten, gehen Sie einfach wie folgt vor:
Es macht dasselbe wie einige dieser anderen Antworten, führt jedoch keinen Datenbankaufruf zum Abrufen eines Objekts durch. Dies ist auch nützlich, wenn Sie eine Kopie eines Objekts erstellen möchten, das noch nicht in der Datenbank vorhanden ist.
quelle
Verwenden Sie den folgenden Code:
quelle
model_to_dict
nimmt einenexclude
Parameter, was bedeutet, dass Sie den separaten nicht benötigenpop
:model_to_dict(instance, exclude=['id'])
Es gibt einen Klon Schnipsel hier , was Sie zu Ihrem Modell hinzufügen können , die dies tut:
quelle
if
jetztif fld.name != old._meta.pk.name
diename
Eigenschaft der_meta.pk
Instanz sein.Wie das geht, wurde den offiziellen Django-Dokumenten in Django1.4 hinzugefügt
https://docs.djangoproject.com/de/1.10/topics/db/queries/#copying-model-instances
Die offizielle Antwort ähnelt der Antwort von miah, aber die Dokumente weisen auf einige Schwierigkeiten bei der Vererbung und verwandten Objekten hin. Sie sollten daher wahrscheinlich sicherstellen, dass Sie die Dokumente lesen.
quelle
stable
anstelle der Versionsnummer in der URL Folgendes zu verwendenIch bin auf ein paar Fallstricke mit der akzeptierten Antwort gestoßen. Hier ist meine Lösung.
Hinweis: Hierbei werden Lösungen verwendet, die in den Django-Dokumenten nicht offiziell genehmigt wurden und in zukünftigen Versionen möglicherweise nicht mehr funktionieren. Ich habe dies in 1.9.13 getestet.
Die erste Verbesserung besteht darin, dass Sie die ursprüngliche Instanz weiterhin verwenden können, indem Sie verwenden
copy.copy
. Selbst wenn Sie nicht beabsichtigen, die Instanz wiederzuverwenden, kann es sicherer sein, diesen Schritt auszuführen, wenn die zu klonende Instanz als Argument an eine Funktion übergeben wurde. Wenn nicht, hat der Aufrufer unerwartet eine andere Instanz, wenn die Funktion zurückkehrt.copy.copy
scheint eine flache Kopie einer Django-Modellinstanz auf die gewünschte Weise zu erzeugen. Dies ist eines der Dinge, die ich nicht dokumentiert gefunden habe, aber es funktioniert durch Beizen und Entpicken, daher wird es wahrscheinlich gut unterstützt.Zweitens werden bei der genehmigten Antwort alle vorab abgerufenen Ergebnisse an die neue Instanz angehängt. Diese Ergebnisse sollten nicht mit der neuen Instanz verknüpft werden, es sei denn, Sie kopieren die zu vielen Beziehungen explizit. Wenn Sie die vorab abgerufenen Beziehungen durchlaufen, erhalten Sie Ergebnisse, die nicht mit der Datenbank übereinstimmen. Das Brechen des Arbeitscodes beim Hinzufügen eines Prefetch kann eine böse Überraschung sein.
Das Löschen
_prefetched_objects_cache
ist eine schnelle und schmutzige Methode, um alle Prefetches zu entfernen. Nachfolgende zu viele Zugriffe funktionieren so, als ob es nie einen Prefetch gegeben hätte. Die Verwendung einer undokumentierten Eigenschaft, die mit einem Unterstrich beginnt, führt wahrscheinlich zu Kompatibilitätsproblemen, funktioniert jedoch vorerst.quelle
_[model_name]_cache
, die ich nach dem Löschen eine neue ID für das zugehörige Modell zuweisen und dann aufrufen konntesave()
. Es könnte immer noch Nebenwirkungen geben, die ich noch nicht festgestellt habe.pk auf None zu setzen ist besser, da sinse Django ein pk korrekt für dich erstellen kann
quelle
Dies ist eine weitere Möglichkeit, die Modellinstanz zu klonen:
quelle
So klonen Sie ein Modell mit mehreren Vererbungsstufen, z. B.> = 2 oder ModelC unten
Bitte beziehen Sie sich hier auf die Frage .
quelle
Versuche dies
quelle