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

1

7

I am trying to make SignalProcessor as per haystack documentation, here is my code:

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)

Full error:

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)

Here you can see documentation - https://django-haystack.readthedocs.io/en/v2.2.0/signal_processors.html#custom-signalprocessors

Here is what I find in django documentation but unable to figure out solution - https://docs.djangoproject.com/en/2.0/_modules/django/dispatch/dispatcher/

How to resolve this error ?

Mcandrew answered 25/7, 2018 at 15:13 Comment(3)
Did you try following the instructions in the error message: def handle_save(self, **kwargs)?Endearment
@DanielRoseman thanks it worked ! why it is showing error in signalsMcandrew
@PankajSharma See my answer I explain itCathrine
C
9

TL;DR:

you should replace

def handle_save(self):

with

def handle_save(self, **kwargs):

The thing is, I don't think you're looking at the right documentation. I'd like to suggest this instead, where it states

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.

Basically, the error handling can be seen in source code for the connect method as,

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

So, since your specified recevier (handle_save in this case) is not accepting **kwargs it inevitably return an error.

Your confusion comes from the fact that you're overriding the built-in handle_save method of haystack. As you can see in the source code, it was initially including the **kwargs, but by overriding it. you changed the method's definition. Thus, resulting in the error.

Cathrine answered 25/7, 2018 at 15:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.