In meinem Modell habe ich:
class Alias(MyBaseModel):
remote_image = models.URLField(max_length=500, null=True, help_text="A URL that is downloaded and cached for the image. Only
used when the alias is made")
image = models.ImageField(upload_to='alias', default='alias-default.png', help_text="An image representing the alias")
def save(self, *args, **kw):
if (not self.image or self.image.name == 'alias-default.png') and self.remote_image :
try :
data = utils.fetch(self.remote_image)
image = StringIO.StringIO(data)
image = Image.open(image)
buf = StringIO.StringIO()
image.save(buf, format='PNG')
self.image.save(hashlib.md5(self.string_id).hexdigest() + ".png", ContentFile(buf.getvalue()))
except IOError :
pass
Welches funktioniert großartig zum ersten Mal die remote_image
Änderungen.
Wie kann ich ein neues Bild abrufen, wenn jemand remote_image
den Alias geändert hat ? Und zweitens, gibt es eine bessere Möglichkeit, ein Remote-Image zwischenzuspeichern?
django
image
caching
django-models
Paul Tarjan
quelle
quelle
save()
es WIEDER aufrufen , funktioniert es weiterhin ordnungsgemäß.Ich benutze folgendes Mixin:
Verwendungszweck:
Hinweis
Bitte beachten Sie, dass diese Lösung nur im Kontext der aktuellen Anfrage funktioniert. Somit ist es vor allem für einfache Fälle geeignet. In einer gleichzeitigen Umgebung, in der mehrere Anforderungen dieselbe Modellinstanz gleichzeitig bearbeiten können, benötigen Sie definitiv einen anderen Ansatz.
quelle
Der beste Weg ist mit einem
pre_save
Signal. Vielleicht war es noch keine Option in '09, als diese Frage gestellt und beantwortet wurde, aber jeder, der dies heute sieht, sollte es so machen:quelle
Und jetzt zur direkten Antwort: Eine Möglichkeit zu überprüfen, ob sich der Wert für das Feld geändert hat, besteht darin, die Originaldaten aus der Datenbank abzurufen, bevor die Instanz gespeichert wird. Betrachten Sie dieses Beispiel:
Gleiches gilt für die Arbeit mit einem Formular. Sie können es an der Bereinigungs- oder Speichermethode einer ModelForm erkennen:
quelle
pk is not None
Hören Sie auf, den Leuten zu sagen, dass sie dies überprüfen sollen. Dies gilt beispielsweise nicht, wenn Sie ein UUIDField verwenden. Das ist nur ein schlechter Rat.@transaction.atomic
Seit der Veröffentlichung von Django 1.8 können Sie die Klassenmethode from_db verwenden, um den alten Wert von remote_image zwischenzuspeichern. Anschließend können Sie in der Speichermethode den alten und den neuen Wert des Felds vergleichen, um zu überprüfen, ob sich der Wert geändert hat.
quelle
new._loaded_remote_image = new.remote_image
?from_db
aufgerufen wirdrefresh_from_db
, werden die Attribute der Instanz (dh geladen oder vorher) nicht aktualisiert. Als Ergebnis kann ich keinen Grund, warum dies ist besser als ,__init__
wie Sie noch 3 Fälle behandeln müssen:__init__
/from_db
,refresh_from_db
undsave
.Beachten Sie, dass die Feldänderungsverfolgung in django-model-utils verfügbar ist.
https://django-model-utils.readthedocs.org/en/latest/index.html
quelle
Wenn Sie ein Formular verwenden, können Sie die geänderten_Daten ( Dokumente ) des Formulars verwenden :
quelle
Ich bin etwas spät zur Party, aber ich habe auch diese Lösung gefunden: Django Dirty Fields
quelle
Ab Django 1.8 gibt es die
from_db
Methode, wie Serge erwähnt. Tatsächlich enthalten die Django-Dokumente diesen speziellen Anwendungsfall als Beispiel:https://docs.djangoproject.com/de/dev/ref/models/instances/#customizing-model-loading
quelle
Dies funktioniert bei mir in Django 1.8
quelle
Sie können Django-Modell-Änderungen verwenden , um dies ohne eine zusätzliche Datenbanksuche zu tun:
quelle
Noch eine späte Antwort, aber wenn Sie nur versuchen zu sehen, ob eine neue Datei in ein Dateifeld hochgeladen wurde, versuchen Sie Folgendes: (angepasst aus Christopher Adams 'Kommentar unter dem Link http://zmsmith.com/2010/05/django -check-wenn-ein-Feld-geändert hat / in Zachs Kommentar hier)
Aktualisierter Link: https://web.archive.org/web/20130101010327/http://zmsmith.com:80/2010/05/django-check-if-a-field-has-changed/
quelle
pre_save
Empfänger verwenden. Danke, dass du das geteilt hast!Die optimale Lösung ist wahrscheinlich eine, die weder eine zusätzliche Datenbankleseoperation vor dem Speichern der Modellinstanz noch eine weitere Django-Bibliothek enthält. Aus diesem Grund sind die Lösungen von laffuste vorzuziehen. Im Kontext einer Admin-Site kann man einfach
save_model
diehas_changed
-Methode überschreiben und dort die Methode des Formulars aufrufen , genau wie in der obigen Antwort von Sion. Sie kommen zu so etwas, indem Sie sich auf Sions Beispieleinstellung stützen, aber verwendenchanged_data
, um jede mögliche Änderung zu erhalten:save_model
:https://docs.djangoproject.com/de/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
changed_data
Methode für ein Feld:https://docs.djangoproject.com/de/1.10/ref/forms/api/#django.forms.Form.changed_data
quelle
Obwohl dies Ihre Frage nicht wirklich beantwortet, würde ich dies auf eine andere Weise tun.
Löschen Sie einfach das
remote_image
Feld, nachdem Sie die lokale Kopie erfolgreich gespeichert haben. Dann können Sie in Ihrer Speichermethode das Bild immer aktualisieren, wennremote_image
es nicht leer ist.Wenn Sie einen Verweis auf die URL behalten möchten, können Sie ein nicht bearbeitbares boolesches Feld verwenden, um das Caching-Flag anstelle des
remote_image
Felds selbst zu behandeln.quelle
Ich hatte diese Situation, bevor meine Lösung darin bestand, die
pre_save()
Methode der Zielfeldklasse zu überschreiben. Sie wird nur aufgerufen, wenn das Feld geändert wurde, was mit dem FileField-Beispiel nützlich ist:
Nachteil:
Nicht nützlich, wenn Sie eine (post_save) Operation wie die Verwendung des erstellten Objekts in einem Job ausführen möchten (wenn sich ein bestimmtes Feld geändert hat).
quelle
Verbesserung der @ josh-Antwort für alle Bereiche:
Nur um dies zu verdeutlichen, arbeitet der getattr daran, Felder wie
person.name
mit Strings zu erhalten (dhgetattr(person, "name")
quelle
Ich habe das Mixin von @livskiy wie folgt erweitert:
und das DictField ist:
Sie können es verwenden, indem Sie es in Ihren Modellen erweitern. Beim Synchronisieren / Migrieren wird ein _dict-Feld hinzugefügt, in dem der Status Ihrer Objekte gespeichert wird
quelle
Wie wäre es mit der Lösung von David Cramer:
http://cramer.io/2010/12/06/tracking-changes-to-fields-in-django/
Ich hatte Erfolg damit:
quelle
Eine Modifikation der Antwort von @ ivanperelivskiy:
Dies verwendet stattdessen die öffentliche Methode von django 1.10
get_fields
. Dies macht den Code zukunftssicherer, enthält aber vor allem auch Fremdschlüssel und Felder, in denen editierbar = Falsch ist.Als Referenz ist hier die Implementierung von
.fields
quelle
Hier ist eine andere Möglichkeit, dies zu tun.
Gemäß Dokumentation: Objekte validieren
"Der zweite Schritt, den full_clean () ausführt, ist das Aufrufen von Model.clean (). Diese Methode sollte überschrieben werden, um eine benutzerdefinierte Validierung für Ihr Modell durchzuführen. Diese Methode sollte verwendet werden, um eine benutzerdefinierte Modellvalidierung bereitzustellen und Attribute für Ihr Modell zu ändern, falls dies gewünscht wird Sie können es beispielsweise verwenden, um automatisch einen Wert für ein Feld bereitzustellen oder um eine Validierung durchzuführen, die den Zugriff auf mehr als ein einzelnes Feld erfordert: "
quelle
Es gibt ein Attribut __dict__, das alle Felder als Schlüssel und den Wert als Feldwerte enthält. Wir können also nur zwei davon vergleichen
Ändern Sie einfach die Speicherfunktion des Modells in die folgende Funktion
Anwendungsbeispiel:
liefert nur mit den geänderten Feldern eine Ausgabe
quelle
Sehr spät zum Spiel, aber dies ist eine Version von Chris Pratts Antwort , die vor Rennbedingungen schützt und gleichzeitig die Leistung beeinträchtigt, indem sie einen
transaction
Block und verwendetselect_for_update()
quelle
Als Erweiterung der Antwort von SmileyChris können Sie dem Modell für last_updated ein Datum / Uhrzeit-Feld hinzufügen und eine Grenze für das maximale Alter festlegen, das Sie erreichen dürfen, bevor Sie nach einer Änderung suchen
quelle
Das Mixin von @ivanlivski ist großartig.
Ich habe es erweitert
Der aktualisierte Code ist hier verfügbar: https://github.com/sknutsonsf/python-contrib/blob/master/src/django/utils/ModelDiffMixin.py
Um Menschen zu helfen, die Python oder Django noch nicht kennen, werde ich ein vollständigeres Beispiel geben. Diese spezielle Verwendung dient dazu, eine Datei von einem Datenanbieter zu entnehmen und sicherzustellen, dass die Datensätze in der Datenbank die Datei widerspiegeln.
Mein Modellobjekt:
Die Klasse, die die Datei lädt, verfügt über folgende Methoden:
quelle
Wenn Sie kein Interesse an einer überschreibenden
save
Methode haben, können Sie dies tunquelle