@@ -46,15 +46,38 @@ You can also `define and send your own custom signals`_; see below.
46
46
Listening to signals
47
47
====================
48
48
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
51
71
gets called after each HTTP request is finished. We'll be connecting to the
52
72
:data:`~django.core.signals.request_finished` signal.
53
73
74
+ .. _receiver-functions:
75
+
54
76
Receiver functions
55
77
------------------
56
78
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:
58
81
59
82
.. code-block:: python
60
83
@@ -77,6 +100,8 @@ This would be wrong -- in fact, Django will throw an error if you do so. That's
77
100
because at any point arguments could get added to the signal and your receiver
78
101
must be able to handle those new arguments.
79
102
103
+ .. _connecting-receiver-functions:
104
+
80
105
Connecting receiver functions
81
106
-----------------------------
82
107
@@ -115,6 +140,8 @@ The ``receiver`` decorator was added in Django 1.3.
115
140
to be sent. This makes your app's ``models.py`` a good place to put
116
141
registration of signal handlers.
117
142
143
+ .. _connecting-to-specific-signals:
144
+
118
145
Connecting to signals sent by specific senders
119
146
----------------------------------------------
120
147
@@ -146,10 +173,34 @@ Different signals use different objects as their senders; you'll need to consult
146
173
the :doc:`built-in signal documentation </ref/signals>` for details of each
147
174
particular signal.
148
175
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
+
149
199
Defining and sending signals
150
200
============================
151
201
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.
153
204
154
205
Defining signals
155
206
----------------
@@ -176,9 +227,14 @@ Remember that you're allowed to change this list of arguments at any time, so ge
176
227
Sending signals
177
228
---------------
178
229
230
+ There are two ways to send send signals in Django.
231
+
179
232
.. method:: Signal.send(sender, **kwargs)
233
+ .. method:: Signal.send_robust(sender, **kwargs)
180
234
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.
182
238
183
239
For example, here's how sending our ``pizza_done`` signal might look:
184
240
@@ -191,4 +247,26 @@ For example, here's how sending our ``pizza_done`` signal might look:
191
247
pizza_done.send(sender=self, toppings=toppings, size=size)
192
248
...
193
249
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`.
194
270
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