Laden Sie das Django-Objekt aus der Datenbank neu

Lesezeit: 4 Minuten

Benutzer-Avatar
grep

Ist es möglich, den Status eines Django-Objekts aus der Datenbank zu aktualisieren? Ich meine Verhalten in etwa äquivalent zu:

new_self = self.__class__.objects.get(pk=self.pk)
for each field of the record:
    setattr(self, field, getattr(new_self, field))

AKTUALISIEREN: Im Tracker einen Reopen/Wontfix-Krieg gefunden: http://code.djangoproject.com/ticket/901. Verstehe immer noch nicht, warum die Betreuer das nicht mögen.

  • In einem gewöhnlichen SQL-Kontext macht dies keinen Sinn. Das Datenbankobjekt kann nur geändert werden nach Ihre Transaktion wird beendet und a commmit. Sobald Sie das getan haben, müssen Sie warten, bis die nächste SQL-Transaktion festgeschrieben wird. Warum das tun? Wie lange werden Sie auf die nächste Transaktion warten?

    – S. Lott

    7. Dezember 2010 um 15:55 Uhr

  • Dies scheint eine unnötige Funktion zu sein; Es ist bereits möglich, das Objekt einfach erneut in der Datenbank nachzuschlagen.

    – Stefan

    7. Dezember 2010 um 18:10 Uhr

  • Das hätte ich auch gerne, wurde aber immer wieder abgeschaltet hier

    – kegelförmig

    17. Juni 2011 um 23:34 Uhr

  • Dies ist nicht angemessen, da Django-Modellobjekte Proxys sind. Wenn Sie dieselbe Tabellenzeile in zwei Objekte bekommen – x1 = X.objects.get(id=1); x2 = X.objects.get(id=1), sie werden als gleich getestet, aber sie sind unterschiedliche Objekte und der Status wird nicht geteilt. Sie können beide unabhängig voneinander ändern und speichern – der zuletzt gespeicherte bestimmt den Status der Zeile in der Datenbank. Daher ist es richtig, mit einfacher Zuweisung neu zu laden – x1 = X.objects.get(id=1). Eine Reload-Methode zu haben würde dazu führen, dass viele Leute fälschlicherweise folgern, dass x1.f = ‘neuer Wert’; (x1.f == x2.f) ist wahr.

    – Paul Whip

    6. Februar 2014 um 20:49 Uhr

Ab Django 1.8 ist das Aktualisieren von Objekten eingebaut. Link zu Dokumenten.

def test_update_result(self):
    obj = MyModel.objects.create(val=1)
    MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
    # At this point obj.val is still 1, but the value in the database
    # was updated to 2. The object's updated value needs to be reloaded
    # from the database.
    obj.refresh_from_db()
    self.assertEqual(obj.val, 2)

  • @ fcracker79 Ja, es wurde nur in 1.8 implementiert. Für frühere Versionen von Django verwenden Sie am besten eine der anderen Antworten.

    – Tim Fletcher

    25. August 2015 um 15:46 Uhr

  • Sie sind sich nicht sicher, was „Alle nicht zurückgestellten Felder werden aktualisiert“ in den Dokumenten bedeutet?

    – Yunti

    13. November 2015 um 18:15 Uhr

  • @Yunti Du kannst verschieben Felder oder explizit danach fragen nur eine Teilmenge von Feldern und das resultierende Objekt wird nur teilweise ausgefüllt. refresh_from_db aktualisiert nur solche bereits ausgefüllten Felder.

    – 301_Moved_Permanently

    16. Januar 2019 um 16:37 Uhr

  • Konnte keine Details in den Dokumenten finden, aber es wirft richtig a DoesNotExist Ausnahme, wenn das zugrunde liegende Objekt beim Aufruf gelöscht wurde refresh_from_db. FYI.

    – Tim Tisdall

    17. Januar 2020 um 19:26 Uhr

Ich fand es relativ einfach Laden Sie das Objekt erneut aus der Datenbank so:

x = X.objects.get(id=x.id)

  • Ja, aber… danach müssen Sie alle Verweise auf dieses Objekt aktualisieren. Nicht sehr handlich und fehleranfällig.

    – grep

    4. Februar 2011 um 14:12 Uhr

  • Ich fand dies notwendig, als Celery mein Objekt in der Datenbank außerhalb von Django aktualisierte. Django behielt anscheinend einen Cache des Objekts, da es keine Ahnung hatte, dass es sich geändert hatte.

    – Bob Spryn

    21. August 2012 um 6:16 Uhr

  • aus django.db.models.loading import get_model; Instanz = get_model(Instanz).objects.get(pk=Instanz.pk)

    – Erich

    31. Mai 2013 um 22:22 Uhr


  • @grep hat gerade 2 Stunden verloren, um einen Test für diesen Anwendungsfall zu schreiben: 1: Initialisieren eines Modells; 2: Aktualisieren Sie das Modell über ein Formular; 3: Testen Sie, ob der neue Wert aktualisiert wird…. Also ja, fehleranfällig.

    – vlad-ardelean

    6. Oktober 2014 um 9:06 Uhr

  • Ich finde refresh_from_db löst all diese Probleme.

    – Flimmer

    5. Januar 2017 um 13:47 Uhr

Wie @Flimm betonte, ist dies eine wirklich großartige Lösung:

foo.refresh_from_db()

Dadurch werden alle Daten aus der Datenbank neu in das Objekt geladen.

Sollte es in Bezug auf den Kommentar von @grep nicht möglich sein, Folgendes zu tun:

# Put this on your base model (or monkey patch it onto django's Model if that's your thing)
def reload(self):
    new_self = self.__class__.objects.get(pk=self.pk)
    # You may want to clear out the old dict first or perform a selective merge
    self.__dict__.update(new_self.__dict__)

# Use it like this
bar.foo = foo
assert bar.foo.pk is None
foo.save()
foo.reload()
assert bar.foo is foo and bar.foo.pk is not None

1026530cookie-checkLaden Sie das Django-Objekt aus der Datenbank neu

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy