Django:在post_signal处理程序中引发了DoesNotExist错误。

huangapple go评论48阅读模式
英文:

Django : DoesNotExist Error raised in post_signal handler

问题

I will provide translations for the non-code portions of the text you've provided:

"Trying to delete a Task instance with its subtasks, I encounter DoesNotExist: Task matching query does not exist."

错误消息如下:

"Traceback (most recent call last):
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py", line 218, in get
rel_obj = self.field.get_cached_value(instance)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/mixins.py", line 15, in get_cached_value
return instance._state.fields_cache[cache_name]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'supertask'"

以下是错误消息:

"Traceback (most recent call last):
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py", line 218, in get
rel_obj = self.field.get_cached_value(instance)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/mixins.py", line 15, in get_cached_value
return instance._state.fields_cache[cache_name]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: 'supertask'"

During handling of the above exception, another exception occurred:

在处理上述异常时,发生了另一个异常:

"Traceback (most recent call last):
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/crackers/views.py", line 73, in delete
print(task.delete())
^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/base.py", line 1132, in delete
return collector.delete()
^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/deletion.py", line 512, in delete
signals.post_delete.send(
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 176, in send
return [
^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
(receiver, receiver(signal=self, sender=sender, **named))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/crackers/signals.py", line 10, in reassess_achievement
if instance.supertask is not None and instance.supertask.completed == False:
^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py", line 236, in get
rel_obj = self.get_object(instance)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py", line 199, in get_object
return qs.get(self.field.get_reverse_related_filter(instance))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/query.py", line 637, in get
raise self.model.DoesNotExist(
crackers.models.Task.DoesNotExist: Task matching query does not exist."

到目前为止,我已经发现错误与信号处理程序有关,因为在以下情况下不会出现相同的错误:

  1. 该处理程序不处理 post_delete 信号。也就是说,当我从此处理程序中删除 post_delete 信号时,
  2. instance.supertask 不是 None,
  3. 不存在 instance.subtasks

这些情况是互斥的。如果处理程序不处理 post_delete,那么 instance.supertask 是否为 None 都无关紧要。如果 instance.supertask 不为 None,则实例是否具有子任务都无关紧要。如果实例具有子任务,则 instance.supertask 是否为 None 都无关紧要。

对于上述情况,不会引发错误,并且 delete() 方法成功完成其工作。只有当处理程序处理 post_delete 信号且与实例没有关联的 supertask 时才会引发错误。

错误是因为进入 if 语句时引发的。

以下是处理程序的代码:

@receiver([post_save, post_delete], sender=Task)
def reassess_achievement(sender, instance, **kwargs):
    print(&#39;*&#39;*100)   # 执行
    if instance.supertask is not None and instance.supertask.completed == False:
        print(&#39;#&#39;*100)    # 未执行
        ...

    # 对于其他情况,没有任务要执行。

但是,我仍然必须在删除任务时执行此代码。为什么会引发此错误,以及如何调试它?


更新:

如果我在处理程序中打印 dir(instance),它确实具有 &#39;supertask&#39;。为什么我不能使用 instance.supertask

英文:

Trying to delete a Task instance with its subtasks, I encounter DoesNotExist: Task matching query does not exist.

The following is the error message:

Traceback (most recent call last):
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py&quot;, line 218, in __get__
    rel_obj = self.field.get_cached_value(instance)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/mixins.py&quot;, line 15, in get_cached_value
    return instance._state.fields_cache[cache_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
KeyError: &#39;supertask&#39;

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/core/handlers/exception.py&quot;, line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/core/handlers/base.py&quot;, line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/crackers/views.py&quot;, line 73, in delete
    print(task.delete())
          ^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/base.py&quot;, line 1132, in delete
    return collector.delete()
           ^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/deletion.py&quot;, line 512, in delete
    signals.post_delete.send(
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/dispatch/dispatcher.py&quot;, line 176, in send
    return [
           ^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/dispatch/dispatcher.py&quot;, line 177, in &lt;listcomp&gt;
    (receiver, receiver(signal=self, sender=sender, **named))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/crackers/signals.py&quot;, line 10, in reassess_achievement
    if instance.supertask is not None and instance.supertask.completed == False:
       ^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py&quot;, line 236, in __get__
    rel_obj = self.get_object(instance)
              ^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py&quot;, line 199, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File &quot;/Users/thebjko/dev/TrackCracker/venv/lib/python3.11/site-packages/django/db/models/query.py&quot;, line 637, in get
    raise self.model.DoesNotExist(
crackers.models.Task.DoesNotExist: Task matching query does not exist.

So far, I have figured out that the error is related to signal handler, since the same error does not occur when

  1. the handler does not handle post_delete signal. That is when I remove post_delete signal from this handler,
  2. instance.supertask is not None
  3. there does not exist instance.subtasks.

These cases are mutually exclusive. If the handler does not handle post_delete, it does not matter if instance.supertask is None or not. If instance.supertask is not None, it does not matter if the instance has subtasks or not. If the instance has subtasks, it does not matter if instance.supertask is None or not.

For the above cases, the error is not raised and delete() method does its job successfully. The error is only raised when the handler handles post_delete signal, and there is no supertask related with the instance if it has subtasks.

The error is raised as it enters if statement.

The following is the handler:

@receiver([post_save, post_delete], sender=Task)
def reassess_achievement(sender, instance, **kwargs):
    print(&#39;*&#39;*100)   # executed
    if instance.supertask is not None and instance.supertask.completed == False:
        print(&#39;#&#39;*100)    # not executed
        ...

    # No job for other cases.

But I still have to execute this code whenever I delete task. Why is this error raised and how can I debug it?


UPDATE:

If I print dir(instance) inside the handler, it does have &#39;supertask&#39;. Why can't I use instance.supertask?

答案1

得分: 0

文档中:

> 请注意,对象将不再存在于数据库中,因此对这个实例要非常小心。

所以我必须使用pre_delete代替。

英文:

From documentation

> Note that the object will no longer be in the database, so be very careful what you do with this instance.

So I have to use pre_delete instead.

huangapple
  • 本文由 发表于 2023年6月29日 09:44:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577597.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定