Opened 7 years ago

Closed 7 years ago

Last modified 4 years ago

#7648 closed (invalid)

Signal being throw too many times...

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

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 Changed 7 years ago by russellm

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

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 Changed 7 years ago by italomaia

  • Resolution invalid deleted
  • Status changed from closed to reopened

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 Changed 7 years ago by russellm

  • Resolution set to invalid
  • Status changed from reopened to closed

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 Changed 4 years ago by jacob

  • milestone 1.0 beta deleted

Milestone 1.0 beta deleted

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