2

I am trying to create a background job with RQ:

import django_rq                                                         


    def _send_password_reset_email_async(email):                             
        print(email)                                                         

    # Django admin action to send reset password emails                                                                 
    def send_password_reset_email(modeladmin, request, queryset):            
        for user in queryset:                                                
            django_rq.enqueue(_send_password_reset_email_async, user.email)  
    send_password_reset_email.short_description = 'Send password reset email'

I keep getting this error though, and it seems like I am doing something silly?

Traceback (most recent call last):
  File "/home/lee/Code/cas/venv/lib/python3.4/site-packages/rq/worker.py", line 568, in perform_job
    rv = job.perform()
  File "/home/lee/Code/cas/venv/lib/python3.4/site-packages/rq/job.py", line 

495, in perform
    self._result = self.func(*self.args, **self.kwargs)
  File "/home/lee/Code/cas/venv/lib/python3.4/site-packages/rq/job.py", line 206, in func
    return import_attribute(self.func_name)
  File "/home/lee/Code/cas/venv/lib/python3.4/site-packages/rq/utils.py", line 151, in import_attribute
    return getattr(module, attribute)
AttributeError: 'module' object has no attribute '_send_password_reset_email_async

'

Lee
  • 8,354
  • 14
  • 55
  • 90

8 Answers8

12

Adding a comment as I too ran into this error:

The Django dev webserver dynamically rereloads when you change your code, but the rqworker process does not. So if you add/modify a task & immediately call it, you may run into this error as the new code (your web code) tries to call the old code (the RQ task).

Stop/restart rqworker and you're ok.

Richard Barran
  • 331
  • 2
  • 6
2

So,what you actually need to do is that import the module in some file and then perform delay on it. @MrE,So it's not necessary to import it in the init.py file

1

This problem occurs when you run your rqworker from home or a different directory. In the command prompt navigate to the directory where your python file is present and then run rqworker command.

Note: Watch out for the port where your redis server is running, if its not default i.e. 6379 then you will have to mention the port while running rqworker like this, your_python_file_directory_path $ rqworker --url redis://localhost:port

0

How about enclosing the _send_password_reset_email_async inside the reset_email function -

def send_password_reset_email(modeladmin, request, queryset):  
    def _send_password_reset_email_async(email):                             
        print(email)  

    for user in queryset:                                                
        django_rq.enqueue(_send_password_reset_email_async, user.email)  

send_password_reset_email.short_description = 'Send password reset email'
hspandher
  • 15,934
  • 2
  • 32
  • 45
0

Copying the comment of @richardbarran in https://github.com/ui/django-rq/issues/125

Rqworker does not dynamically reload when you change your code, but the Django dev webserver does So if you add/modify a task & immediately call it, you may run into this error as the new code (your web code) tries to call the old code (the RQ task).

Stop/restart rqworker and you're ok.

Raul Benitez
  • 35
  • 1
  • 7
0

I had a similar problem, and making sure to import the module in the __init__.py of the app fixed the problem.

MrE
  • 19,584
  • 12
  • 87
  • 105
0

try to write your function in another file, import it as a module

# in my_utility.py
def send_password_reset_email_async(email):                             
    print(email)  

then

import django_rq                                                         
from my_utility import send_password_reset_email_async

#def _send_password_reset_email_async(email):                             
#   print(email)                                                         

# Django admin action to send reset password emails                                                                 
def send_password_reset_email(modeladmin, request, queryset):            
    for user in queryset:                                                
        django_rq.enqueue(send_password_reset_email_async, user.email)  
send_password_reset_email.short_description = 'Send password reset email'                                                       
tinyhare
  • 2,271
  • 21
  • 25
0

In my case I didn't put the task inside a tasks.py file...

Vincent
  • 1,494
  • 12
  • 26