Opened 16 years ago

Closed 16 years ago

Last modified 13 years ago

#7648 closed (invalid)

Signal being throw too many times...

Reported by: italomaia Owned by: nobody
Component: Uncategorized Version: dev
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I tried to use the syncdb signal and noticed that, even being connected once, it was thrown more then once during the database sync. Shouldn't it
happen just once?

Change History (4)

comment:1 by Russell Keith-Magee, 16 years ago

Resolution: invalid
Status: newclosed

The signal will only be emitted once. It's more than likely you have multiple registrations of a single listener on the signal. However, without detailed instructions on how to reproduce your problem, it's impossible to tell for certain. Marking invalid in the absence of sufficient detail to triage.

comment:2 by italomaia, 16 years ago

Resolution: invalid
Status: closedreopened

Fair enough. To reproduce this behavior, do as follow:
django-admin.py startproject bad
cd bad
python manage.py startapp badsignal
configure your database
edit urls to

from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Example:
    (r'^bad/', 'bad.badsignal.views.index'),
)

go to badsignal and edit views.py to

# Create your views here.
from django.http import HttpResponse


from badsignal.models import Test

def index(request):
    Test.objects.create()    
    return HttpResponse("Signal test.", mimetype="text/plain")

change models to

from django.db import models
from django.core.urlresolvers import reverse
from django.db.models import signals
from django.dispatch import dispatcher

# Create your models here.

class Test(models.Model):
    counter = models.IntegerField(default=0, blank=True)

def test_pre_save(sender, instance, signal, *args, **kwargs):
    instance.counter+=1
    print "UPDATED TEST ", instance.counter

dispatcher.connect( test_pre_save, sender=Test, signal=signals.post_save )

The evil is done! start your development server and access
http://localhost:8000/bad/
In your console, you should see:

UPDATED TEST 1
UPDATED TEST 2 <== attention! Called twice!
COUNTER 1

comment:3 by Russell Keith-Magee, 16 years ago

Resolution: invalid
Status: reopenedclosed

This isn't enough detail to replicate the problem completely, but let me fill in the missing pieces. Your project refers to the application "bad" in three places:

  • In the view, importing models.py
  • In the admin, importing models.py
  • In the settings, in INSTALLED_APPS.

Between these three places, you are referring to the application in two different ways:

  • from bad.models import *)
  • from badproject.bad.models import *

This means you are importing the application twice, and as a result, the signal is registered twice. This is a quirk of python model importing, and there isn't much we can do to work around this. The only solutions are:

  • Be consistent in the use of imports (i.e., only ever import bad.models.py)
  • Put your registration somewhere else that won't be imported twice.

comment:4 by Jacob, 13 years ago

milestone: 1.0 beta

Milestone 1.0 beta deleted

Note: See TracTickets for help on using tickets.
Back to Top