Skip to content

Commit e4c0c37

Browse files
author
Gabriel Hurley
committed
Fixed #11441 -- Improved signal topic guide, particularly regarding the weak and dispatch_uid parameters to the Signal.connect method. Thanks to Mike_A and sayane for the report, and gremmie for the draft patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14337 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 6737570 commit e4c0c37

File tree

1 file changed

+83
-5
lines changed

1 file changed

+83
-5
lines changed

docs/topics/signals.txt

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,38 @@ You can also `define and send your own custom signals`_; see below.
4646
Listening to signals
4747
====================
4848

49-
To receive a signal, you need to register a *receiver* function that gets called
50-
when the signal is sent. Let's see how this works by registering a signal that
49+
To receive a signal, you need to register a *receiver* function that gets
50+
called when the signal is sent by using the
51+
:meth:`.Signal.connect` method:
52+
53+
.. method:: Signal.connect(receiver, [sender=None, weak=True, dispatch_uid=None])
54+
55+
:param receiver: The callback function which will be connected to this
56+
signal. See :ref:`receiver-functions` for more information.
57+
58+
:param sender: Specifies a particular sender to receive signals from. See
59+
:ref:`connecting-to-specific-signals` for more information.
60+
61+
:param weak: Django stores signal handlers as weak references by
62+
default. Thus, if your receiver is a local function, it may be
63+
garbage collected. To prevent this, pass ``weak=False`` when you call
64+
the signal's ``connect()`` method.
65+
66+
:param dispatch_uid: A unique identifier for a signal receiver in cases
67+
where duplicate signals may be sent. See
68+
:ref:`preventing-duplicate-signals` for more information.
69+
70+
Let's see how this works by registering a signal that
5171
gets called after each HTTP request is finished. We'll be connecting to the
5272
:data:`~django.core.signals.request_finished` signal.
5373

74+
.. _receiver-functions:
75+
5476
Receiver functions
5577
------------------
5678

57-
First, we need to define a receiver function. A receiver can be any Python function or method:
79+
First, we need to define a receiver function. A receiver can be any Python
80+
function or method:
5881

5982
.. code-block:: python
6083

@@ -77,6 +100,8 @@ This would be wrong -- in fact, Django will throw an error if you do so. That's
77100
because at any point arguments could get added to the signal and your receiver
78101
must be able to handle those new arguments.
79102

103+
.. _connecting-receiver-functions:
104+
80105
Connecting receiver functions
81106
-----------------------------
82107

@@ -115,6 +140,8 @@ The ``receiver`` decorator was added in Django 1.3.
115140
to be sent. This makes your app's ``models.py`` a good place to put
116141
registration of signal handlers.
117142

143+
.. _connecting-to-specific-signals:
144+
118145
Connecting to signals sent by specific senders
119146
----------------------------------------------
120147

@@ -146,10 +173,34 @@ Different signals use different objects as their senders; you'll need to consult
146173
the :doc:`built-in signal documentation </ref/signals>` for details of each
147174
particular signal.
148175

176+
.. _preventing-duplicate-signals:
177+
178+
Preventing duplicate signals
179+
----------------------------
180+
181+
In some circumstances, the module in which you are connecting signals may be
182+
imported multiple times. This can cause your receiver function to be
183+
registered more than once, and thus called multiples times for a single signal
184+
event.
185+
186+
If this behavior is problematic (such as when using signals to
187+
send an e-mail whenever a model is saved), pass a unique identifier as
188+
the ``dispatch_uid`` argument to identify your receiver function. This
189+
identifier will usually be a string, although any hashable object will
190+
suffice. The end result is that your receiver function will only be
191+
bound to the signal once for each unique ``dispatch_uid`` value.
192+
193+
.. code-block:: python
194+
195+
from django.core.signals import request_finished
196+
197+
request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")
198+
149199
Defining and sending signals
150200
============================
151201

152-
Your applications can take advantage of the signal infrastructure and provide its own signals.
202+
Your applications can take advantage of the signal infrastructure and provide
203+
its own signals.
153204

154205
Defining signals
155206
----------------
@@ -176,9 +227,14 @@ Remember that you're allowed to change this list of arguments at any time, so ge
176227
Sending signals
177228
---------------
178229

230+
There are two ways to send send signals in Django.
231+
179232
.. method:: Signal.send(sender, **kwargs)
233+
.. method:: Signal.send_robust(sender, **kwargs)
180234

181-
To send a signal, call :meth:`Signal.send`. You must provide the ``sender`` argument, and may provide as many other keyword arguments as you like.
235+
To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`.
236+
You must provide the ``sender`` argument, and may provide as many other keyword
237+
arguments as you like.
182238

183239
For example, here's how sending our ``pizza_done`` signal might look:
184240

@@ -191,4 +247,26 @@ For example, here's how sending our ``pizza_done`` signal might look:
191247
pizza_done.send(sender=self, toppings=toppings, size=size)
192248
...
193249

250+
Both ``send()`` and ``send_robust()`` return a list of tuple pairs
251+
``[(receiver, response), ... ]``, representing the list of called receiver
252+
functions and their response values.
253+
254+
``send()`` differs from ``send_robust()`` in how exceptions raised by receiver
255+
functions are handled. ``send()`` does *not* catch any exceptions raised by
256+
receivers; it simply allows errors to propagate. Thus not all receivers may
257+
be notified of a signal in the face of an error.
258+
259+
``send_robust()`` catches all errors derived from Python's ``Exception`` class,
260+
and ensures all receivers are notified of the signal. If an error occurs, the
261+
error instance is returned in the tuple pair for the receiver that raised the error.
262+
263+
Disconnecting signals
264+
=====================
265+
266+
.. method:: Signal.disconnect([receiver=None, sender=None, weak=True, dispatch_uid=None])
267+
268+
To disconnect a receiver from a signal, call :meth:`Signal.disconnect`. The
269+
arguments are as described in :meth:`.Signal.connect`.
194270

271+
The *receiver* argument indicates the registered receiver to disconnect. It may
272+
be ``None`` if ``dispatch_uid`` is used to identify the receiver.

0 commit comments

Comments
 (0)