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.
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.
Das Folgende kann als Abhilfe angesehen werden.
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.
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.
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. ..