Updated advice on connecting signals at startup.

This commit is contained in:
Aymeric Augustin 2013-12-30 13:24:24 +01:00
parent e187caa3af
commit c31d7c4813
2 changed files with 33 additions and 15 deletions

View File

@ -354,6 +354,12 @@ Sent whenever a model class has been "prepared" -- that is, once model has
been defined and registered with Django's model system. Django uses this
signal internally; it's not generally used in third-party applications.
Since this signal is sent during the app registry population process, and
:meth:`AppConfig.setup() <django.apps.AppConfig.setup>` runs after the app
registry is fully populated, receivers cannot be connected in that method.
One possibility is to connect them ``AppConfig.__init__()`` instead, taking
care not to import models or trigger calls to the app registry.
Arguments that are sent with this signal:
``sender``

View File

@ -48,8 +48,7 @@ Listening to signals
====================
To receive a signal, you need to register a *receiver* function that gets
called when the signal is sent by using the
:meth:`.Signal.connect` method:
called when the signal is sent by using the :meth:`Signal.connect` method:
.. method:: Signal.connect(receiver, [sender=None, weak=True, dispatch_uid=None])
@ -115,8 +114,13 @@ manual connect route:
request_finished.connect(my_callback)
Alternatively, you can use a ``receiver`` decorator when you define your
receiver:
Alternatively, you can use a :func:`receiver` decorator:
.. function:: receiver(signal)
:param signal: A signal or a list of signals to connect a function to.
Here's how you connect with the decorator:
.. code-block:: python
@ -129,16 +133,25 @@ receiver:
Now, our ``my_callback`` function will be called each time a request finishes.
Note that ``receiver`` can also take a list of signals to connect a function
to.
.. admonition:: Where should this code live?
You can put signal handling and registration code anywhere you like.
However, you'll need to make sure that the module it's in gets imported
early on so that the signal handling gets registered before any signals need
to be sent. This makes your app's ``models.py`` a good place to put
registration of signal handlers.
Strictly speaking, signal handling and registration code can live anywhere
you like, although it's recommended to avoid the application's root module
and its ``models`` module to minimize side-effects of importing code.
In practice, signal handlers are usually defined in a ``signals``
submodule of the application they relate to. Signal receivers are
connected in the :meth:`~django.apps.AppConfig.setup` method of your
application configuration class. If you're using the :func:`receiver`
decorator, simply import the ``signals`` submodule inside
:meth:`~django.apps.AppConfig.setup`.
.. versionchanged:: 1.7
Since :meth:`~django.apps.AppConfig.setup` didn't exist in previous
versions of Django, signal registration usually happened in the
``models`` module.
.. _connecting-to-specific-signals:
@ -178,10 +191,9 @@ particular signal.
Preventing duplicate signals
----------------------------
In some circumstances, the module in which you are connecting signals may be
imported multiple times. This can cause your receiver function to be
registered more than once, and thus called multiples times for a single signal
event.
In some circumstances, the code connecting receivers to signals may run
multiple times. This can cause your receiver function to be registered more
than once, and thus called multiples times for a single signal event.
If this behavior is problematic (such as when using signals to
send an email whenever a model is saved), pass a unique identifier as