Django signal emitting once, received twice -- Why?
Asked Answered
S

2

16

I'm working with Django signals, but they seem to be received twice, even if emitted once. Here's the code I'm working with (it's a simple wrapper to use Uploadify with Django)...

# Signal-emitting code... emits whenever a file upload is received
# ----------------------------------------------------------------
upload_recieved = django.dispatch.Signal(providing_args=['data'])

def upload(request, *args, **kwargs):
    if request.method == 'POST':
        if request.FILES:
            print 'sending signal'
            upload_recieved.send(sender='uploadify', data=request.FILES['Filedata'])
    return HttpResponse('True')

# Signal-receiving code...
# ----------------------------------------------------------------    
def upload_received_handler(sender, data, **kwargs):
    print 'upload received handler'

print 'connecting signal'
upload_recieved.connect(upload_received_handler)

(I just noticed my signal is spelled wrong)

I'm sure you noticed the print statements in there. On the console, this is what it's showing:

(server starts)
connecting signal

...

sending signal
upload received handler
upload received handler     # << == where is this 2nd one coming from?
127.0.0.1 - - [25/Sep/2009 07:28:22] "POST /uploadify/upload/ HTTP/1.1" 200 -

(also odd is why does Django report the page POST after the signals are fired?)

Stelmach answered 25/9, 2009 at 17:35 Comment(1)
As for why the POST log line comes after, I believe the server waits until the request is finished to log it -- only then can it know whether there was a server error that results in a 500 status code vs. a successful request, how long the request took if the log format contains that, etc.Arsenious
H
22

This has happened to me before and it was due to the module where you are connecting the signal being imported twice. To make sure the signal isn't connected twice you can set the dispatch_uid:

upload_recieved.connect(upload_received_handler, dispatch_uid="some.unique.string.id")

UPDATE It is actually documented here: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

Hg answered 26/9, 2009 at 1:20 Comment(3)
Official link: docs.djangoproject.com/en/dev/topics/signals/…Accelerando
Is there a best practice for determining what the string should be? Adding some arbitrary string to solve the problem seems... arbitrary.Sunbathe
I usually follow the convention 'app.model.model_receiver_function_pertains_to'. A function that's meant to be called every time a Project is saved might be decorated as follows: @receiver(post_save, sender=Project, dispatch_uid='projects.project.reindex').Yeorgi
Q
1

you can check "created" argument in your function that you are connecting with signal which returns True and False respectively. Created will be True only when a new object is created.

def task_feedback_status_handler(sender, instance, created, **kwargs):
    if created:
        do something
post_save.connect(task_feedback_status_handler, sender=Feedback)
Quathlamba answered 20/8, 2020 at 6:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.