Django 1.7:绕过未保存的实例抛出" unhashable"例外

时间:2014-09-28 02:51:36

标签: python django django-models django-1.7

我目前正在迁移到Django 1.7。我有一些信号传递未保存的模型实例,现在抛出TypeError: Model instances without primary key value are unhashable

我想知道Django pre_save信号如何在实例周围传递?我正在查看文档,甚至找到了在1.7(https://github.com/django/django/commit/6af05e7a0f0e4604d6a67899acaa99d73ec0dfaa)中实现此功能的提交,我只是不知道它是如何工作的。

有人可以向我解释pre_save是如何解决这个问题的,或者我如何绕过这个限制?感谢。

以下示例代码:

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

回溯:

  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

1 个答案:

答案 0 :(得分:7)

看起来Django将sender存储在一个缓存中,用于在信号调度期间进行查找。这需要sender可以清除,这对于没有pk的模型实例不起作用。

这不会影响pre_save等人的原因。按照惯例,sender是模型,而不是模型实例instance在其自己的参数中传递。请参阅the documentation

该解决方案很容易使用该类作为sender,并将该实例作为参数传递。

(如果这只是在偶然发生之前有效。修复的bug导致所有未保存的模型实例评估为相等。)