Search code examples
djangocelery

Django - Celery - missing required positional argument - 'NoneType' object has no attribute 'delay'


When I define a task with parameters, I get the error:

missing 1 required positional argument 

Though, I'm not sure if it really is missing one. I am passing the argument in delay in views.py. I tried defining the task without any arguments and it says:

NoneType' object has no attribute 'delay'

Besides, when I run a celery worker, it recognizes the task:

[tasks]
  . posts.tasks.say_hello_task

Why is this happening?

celery.py:

from celery import Celery
import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zwitter.settings")

app = Celery("zwitter")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()

settings.py:

CELERY_ACCEPT_CONTENT = ["json"]
CELERY_RESULT_ACCEPT_CONTENT = ["json"]
CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json"
CELERY_TASK_ALWAYS_EAGER = False
CELERY_RESULT_BACKEND = "rpc://"
CELERY_BROKER_URL = "amqp://"
CELERY_RESULT_EXPIRES = timedelta(days=1)
CELERY_WORKER_PREFETCH_MULTIPLIER = 1

tasks.py:

@shared_task
def say_hello_task(name):
    print(f"hello {name}")

views.py:

tasks.say_hello_task().delay("john")

Solution

  • Your say_hello_task() function returns None. While calling tasks.say_hello_task().delay("john"), you are effectively running the function in the current process and calling .delay on None, as evident from the error. As @mamareza pointed out, you have to call say_hello_task.delay("john").

    app.send_task is quite useful when you want dependencies of your services minimal. Internally .delay infers the task_name from decorated function, serialises with arguments and sends over your RabbitMQ queue for execution in a different process. While also running celery, run in either DEBUG or INFO mode to see all the logs it emits.