[PYTHON] Über "RuntimeWarning: Die Django-Version der eingelegten Modellinstanz ist nicht angegeben"

Dieser Artikel ist der Artikel zum 6. Tag von Python Part 2 Advent Calendar 2015.

Wenn Sie Django von 1.7 auf 1.8 oder höher aktualisieren,

RuntimeWarning: Pickled model instance's Django version is not specified.
  obj = pickle.loads(value)

Möglicherweise wird eine solche Warnung angezeigt.

Ich habe mich gefragt, ob es beim Deserialisieren einer Modellinstanz mit Pickle immer vorkommen würde, aber manchmal wurde diese Warnung nicht angezeigt und die Bedingungen waren unbekannt. Deshalb habe ich die Ursache untersucht.

Grund zur Warnung

Einfach ausgedrückt, passiert es, wenn Sie Modelldaten deserialisieren, die in einer Anwendung mit Django 1.7 oder früher in einer Anwendung mit Django 1.8 oder höher serialisiert wurden.

Der Code, der die Warnung verursacht, ist hier.

Sie können es einfach reproduzieren, indem Sie eine Umgebung mit 1.7, 1.8 / 1.9 erstellen, die mit virtualenv usw. installiert ist, und die Version mit derselben Anwendung wechseln.

Stellen Sie den Cache mit der virtuellen Umgebung von Django 1.7 wie folgt ein.

$ python manage.py shell
>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from myapp.models import MyModel
>>> obj = MyModel.objects.get(pk=1)
>>> caches['default'].set('my-model-instance', pickle.dumps(obj))

Deserialisieren Sie die Modellinstanz aus dem Cache mit der virtuellen Umgebung von Django 1.8 wie folgt.

$ python manage.py shell
>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from myapp.models import MyModel
>>> pickle.loads(caches['default'].get('my-model-instance'))
<string>:1: RuntimeWarning: Pickled model instance's Django version is not specified.

Problemumgehung

Das Folgende kann als Abhilfe angesehen werden.

ignorieren

Ich bin mir nicht sicher, aber soweit ich die Kommentare im Django-Quellcode lese, scheint es ohne die faul geladene Eigenschaft in defer keine Wirkung zu haben.

Außerdem werden flüchtige Caches wie Memcache im Laufe der Zeit durch neue Caches ersetzt, sodass das Problem behoben werden sollte.

Leeren Sie den Cache, wenn Django aktualisiert wird

Ich empfehle es nicht.

$ python manage.py shell
>>> from django.core.cache import caches
>>> caches['default'].clear()

Oder Sie können KEY_PREFIX in settings.py festlegen Ändern Sie com / de / 1.9 / ref / settings / # Schlüsselpräfix) oder erhöhen Sie VERSION. Hat fast den gleichen Effekt wie das Löschen des Caches.

Ändern Sie nur den Cache-Schlüssel der eingelegten Daten

Dies ist die Methode, die ich zu fangen versuche.

Wenn Sie die Versionsnummer von Django in den Schlüssel des Caches eingeben, wird automatisch ein anderer Cache für jede Version verwendet, auch wenn die Version in Zukunft aktualisiert wird.

>>> from django.core.cache import caches
>>> from django.utils.six.moves import cPickle as pickle
>>> from django.utils.version import get_version
>>> from myapp.models import MyModel
>>> obj = MyModel.objects.get(pk=1)
>>> caches['default'].set('{}:my-model-instance'.format(get_version()), pickle.dumps(obj))

Das Problem tritt nur beim Zwischenspeichern der Instanz des eingelegten Modells auf. Wenn Sie also das relevante Teil wie oben beschrieben reparieren, sollten Sie auch dann kein Problem haben, wenn Sie auf 1.9 oder höher aktualisieren. ..

Recommended Posts

Über "RuntimeWarning: Die Django-Version der eingelegten Modellinstanz ist nicht angegeben"
[Django-Fehler] Das Objekt 'RenameAttributes' ist nicht iterierbar
Über die Sache, dass Softmax am Ende von Torchvisions Modell nicht benötigt wird.