Django 1.7: Walking around unsaved instances throws an "uncorrectable" exception
I am currently migrating to Django 1.7. I have some signals that send an unsaved model instance which is now being cast TypeError: Model instances without primary key value are unhashable
.
I'm wondering how Django passes a pre_save
signal around an instance? I go through the docs and even found a commit that implemented this in 1.7 ( https://github.com/django/django/commit/6af05e7a0f0e4604d6a67899acaa99d73ec0dfaa ) and I just don't know how to do it even works.
Can someone explain to me how pre_save will get around this or how I can get around this limitation myself? Thank.
Sample code below:
from django.dispatch import Signal
send_text = Signal()
unsaved_model = SomeModel() # note that neither `create` or `.save()` are being called
send_text.send(sender=unsaved_model) # error gets thrown when this gets called
Traceback:
File "/home/ubuntu/fangsterr-app/notifications/models.py", line 43, in send
send_text.send(sender=self)
File "/home/ubuntu/virtualenvs/venv-2.7.5/lib/python2.7/site-packages/django/dispatch/dispatcher.py", line 194, in send
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
File "/home/ubuntu/virtualenvs/venv-2.7.5/lib/python2.7/site-packages/django/db/models/base.py", line 484, in __hash__
raise TypeError("Model instances without primary key value are unhashable")
TypeError: Model instances without primary key value are unhashable
source to share
It looks like Django stores sender
in a cache that it uses to look up while sending a signal. This requires it to sender
be hashable, which doesn't work on a model instance without pk
.
The reason for this does not affect pre_save
et al. is that, by convention, sender
is a model class, not a model instance. instance
passed in its own argument. See the documentation .
The solution is easy to use the class as sender
and pass an instance as an argument.
(If it worked before it was just an accident. Fixed a bug where all uncolored instances of the model were evaluated as equal.)
source to share