ValueError: Signal receivers must accept keyword arguments (**kwargs). when using Haystack

ValueError: Signal receivers must accept keyword arguments (**kwargs). when using Haystack

我正在尝试根据 haystack 文档制作 SignalProcessor,这是我的代码:

from haystack.signals import RealtimeSignalProcessor
from products.models import ProductCreateModel
from django.db import models
from star_ratings.models import Rating

class BatchingSignalProcessor(RealtimeSignalProcessor):

   def handle_save(self):
        using_backends = self.connection_router.for_write(instance=instance)

        for using in using_backends:
            try:
                index = self.connections[using].get_unified_index().get_index(instance.__class__)
                index.update_object(instance, using=using)
            except NotHandled:
                # TODO: Maybe log it or let the exception bubble?
                pass


    def setup(self):
        models.signals.post_save.connect(self.handle_save, sender=Rating)

完整错误:

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x00000240811ED400>
Traceback (most recent call last):
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\utils\autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\core\management\commands\runserver.py", line 112, in inner_run
    autoreload.raise_last_exception()
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\utils\autoreload.py", line 248, in raise_last_exception
    raise _exception[1]
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\core\management\__init__.py", line 327, in execute
    autoreload.check_errors(django.setup)()
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\utils\autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\apps\registry.py", line 120, in populate
    app_config.ready()
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\haystack\apps.py", line 28, in ready
    self.signal_processor = signal_processor_class(connections, connection_router)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\haystack\signals.py", line 20, in __init__
    self.setup()
  File "c:\Users\lenovo\Desktop\My_Django_Stuff\bekaim\search\signals.py", line 21, in setup
    models.signals.post_save.connect(self.handle_save, sender=Rating)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\signals.py", line 28, in connect
    weak=weak, dispatch_uid=dispatch_uid,
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\db\models\signals.py", line 23, in _lazy_method
    return partial_method(sender)
  File "C:\Users\lenovo\AppData\Local\conda\conda\envs\myDjangoEnv\lib\site-packages\django\dispatch\dispatcher.py", line 90, in connect
    raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")
ValueError: Signal receivers must accept keyword arguments (**kwargs)

在这里你可以看到文档 - https://django-haystack.readthedocs.io/en/v2.2.0/signal_processors.html#custom-signalprocessors

这是我在 django 文档中找到但无法找到解决方案的内容 - https://docs.djangoproject.com/en/2.0/_modules/django/dispatch/dispatcher/

如何解决这个错误?

TL;DR:

你应该更换

def handle_save(self):

def handle_save(self, **kwargs):

问题是,我认为您没有查看正确的文档。我想改为建议 this,它指出

Notice that the function takes a sender argument, along with wildcard keyword arguments (**kwargs); all signal handlers must take these arguments.

We’ll look at senders a bit later, but right now look at the **kwargs argument. All signals send keyword arguments, and may change those keyword arguments at any time. In the case of request_finished, it’s documented as sending no arguments, which means we might be tempted to write our signal handling as my_callback(sender).

This would be wrong – in fact, Django will throw an error if you do so. That’s because at any point arguments could get added to the signal and your receiver must be able to handle those new arguments.

基本上,错误处理可以在 connect 方法的源代码中看到,

# Check for **kwargs
if not func_accepts_kwargs(receiver):
    raise ValueError("Signal receivers must accept keyword arguments (**kwargs).")

因此,由于您指定的 recevier(在本例中为 handle_save)不接受 **kwargs,因此不可避免地会 return 出错。

您的困惑来自于您重写了 haystack 的内置 handle_save 方法。正如您在源代码中看到的那样,它最初包括 **kwargs,但通过覆盖它。您更改了方法的定义。因此,导致错误。