|
1 ======= |
|
2 Signals |
|
3 ======= |
|
4 |
|
5 .. module:: django.dispatch |
|
6 :synopsis: Signal dispatch |
|
7 |
|
8 Django includes a "signal dispatcher" which helps allow decoupled applications |
|
9 get notified when actions occur elsewhere in the framework. In a nutshell, |
|
10 signals allow certain *senders* to notify a set of *receivers* that some action |
|
11 has taken place. They're especially useful when many pieces of code may be |
|
12 interested in the same events. |
|
13 |
|
14 Django provides a :doc:`set of built-in signals </ref/signals>` that let user |
|
15 code get notified by Django itself of certain actions. These include some useful |
|
16 notifications: |
|
17 |
|
18 * :data:`django.db.models.signals.pre_save` & |
|
19 :data:`django.db.models.signals.post_save` |
|
20 |
|
21 Sent before or after a model's :meth:`~django.db.models.Model.save` method |
|
22 is called. |
|
23 |
|
24 * :data:`django.db.models.signals.pre_delete` & |
|
25 :data:`django.db.models.signals.post_delete` |
|
26 |
|
27 Sent before or after a model's :meth:`~django.db.models.Model.delete` |
|
28 method is called. |
|
29 |
|
30 * :data:`django.db.models.signals.m2m_changed` |
|
31 |
|
32 Sent when a :class:`ManyToManyField` on a model is changed. |
|
33 |
|
34 * :data:`django.core.signals.request_started` & |
|
35 :data:`django.core.signals.request_finished` |
|
36 |
|
37 Sent when Django starts or finishes an HTTP request. |
|
38 |
|
39 See the :doc:`built-in signal documentation </ref/signals>` for a complete list, |
|
40 and a complete explanation of each signal. |
|
41 |
|
42 You can also `define and send your own custom signals`_; see below. |
|
43 |
|
44 .. _define and send your own custom signals: `defining and sending signals`_ |
|
45 |
|
46 Listening to signals |
|
47 ==================== |
|
48 |
|
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 |
|
71 gets called after each HTTP request is finished. We'll be connecting to the |
|
72 :data:`~django.core.signals.request_finished` signal. |
|
73 |
|
74 .. _receiver-functions: |
|
75 |
|
76 Receiver functions |
|
77 ------------------ |
|
78 |
|
79 First, we need to define a receiver function. A receiver can be any Python |
|
80 function or method: |
|
81 |
|
82 .. code-block:: python |
|
83 |
|
84 def my_callback(sender, **kwargs): |
|
85 print "Request finished!" |
|
86 |
|
87 Notice that the function takes a ``sender`` argument, along with wildcard |
|
88 keyword arguments (``**kwargs``); all signal handlers must take these arguments. |
|
89 |
|
90 We'll look at senders `a bit later`_, but right now look at the ``**kwargs`` |
|
91 argument. All signals send keyword arguments, and may change those keyword |
|
92 arguments at any time. In the case of |
|
93 :data:`~django.core.signals.request_finished`, it's documented as sending no |
|
94 arguments, which means we might be tempted to write our signal handling as |
|
95 ``my_callback(sender)``. |
|
96 |
|
97 .. _a bit later: `connecting to signals sent by specific senders`_ |
|
98 |
|
99 This would be wrong -- in fact, Django will throw an error if you do so. That's |
|
100 because at any point arguments could get added to the signal and your receiver |
|
101 must be able to handle those new arguments. |
|
102 |
|
103 .. _connecting-receiver-functions: |
|
104 |
|
105 Connecting receiver functions |
|
106 ----------------------------- |
|
107 |
|
108 Next, we'll need to connect our receiver to the signal: |
|
109 |
|
110 .. code-block:: python |
|
111 |
|
112 from django.core.signals import request_finished |
|
113 |
|
114 request_finished.connect(my_callback) |
|
115 |
|
116 Now, our ``my_callback`` function will be called each time a request finishes. |
|
117 |
|
118 .. admonition:: Where should this code live? |
|
119 |
|
120 You can put signal handling and registration code anywhere you like. |
|
121 However, you'll need to make sure that the module it's in gets imported |
|
122 early on so that the signal handling gets registered before any signals need |
|
123 to be sent. This makes your app's ``models.py`` a good place to put |
|
124 registration of signal handlers. |
|
125 |
|
126 .. _connecting-to-specific-signals: |
|
127 |
|
128 Connecting to signals sent by specific senders |
|
129 ---------------------------------------------- |
|
130 |
|
131 Some signals get sent many times, but you'll only be interested in receiving a |
|
132 certain subset of those signals. For example, consider the |
|
133 :data:`django.db.models.signals.pre_save` signal sent before a model gets saved. |
|
134 Most of the time, you don't need to know when *any* model gets saved -- just |
|
135 when one *specific* model is saved. |
|
136 |
|
137 In these cases, you can register to receive signals sent only by particular |
|
138 senders. In the case of :data:`django.db.models.signals.pre_save`, the sender |
|
139 will be the model class being saved, so you can indicate that you only want |
|
140 signals sent by some model: |
|
141 |
|
142 .. code-block:: python |
|
143 |
|
144 from django.db.models.signals import pre_save |
|
145 from myapp.models import MyModel |
|
146 |
|
147 def my_handler(sender, **kwargs): |
|
148 ... |
|
149 |
|
150 pre_save.connect(my_handler, sender=MyModel) |
|
151 |
|
152 The ``my_handler`` function will only be called when an instance of ``MyModel`` |
|
153 is saved. |
|
154 |
|
155 Different signals use different objects as their senders; you'll need to consult |
|
156 the :doc:`built-in signal documentation </ref/signals>` for details of each |
|
157 particular signal. |
|
158 |
|
159 .. _preventing-duplicate-signals: |
|
160 |
|
161 Preventing duplicate signals |
|
162 ---------------------------- |
|
163 |
|
164 In some circumstances, the module in which you are connecting signals may be |
|
165 imported multiple times. This can cause your receiver function to be |
|
166 registered more than once, and thus called multiples times for a single signal |
|
167 event. |
|
168 |
|
169 If this behavior is problematic (such as when using signals to |
|
170 send an e-mail whenever a model is saved), pass a unique identifier as |
|
171 the ``dispatch_uid`` argument to identify your receiver function. This |
|
172 identifier will usually be a string, although any hashable object will |
|
173 suffice. The end result is that your receiver function will only be |
|
174 bound to the signal once for each unique ``dispatch_uid`` value. |
|
175 |
|
176 .. code-block:: python |
|
177 |
|
178 from django.core.signals import request_finished |
|
179 |
|
180 request_finished.connect(my_callback, dispatch_uid="my_unique_identifier") |
|
181 |
|
182 Defining and sending signals |
|
183 ============================ |
|
184 |
|
185 Your applications can take advantage of the signal infrastructure and provide |
|
186 its own signals. |
|
187 |
|
188 Defining signals |
|
189 ---------------- |
|
190 |
|
191 .. class:: Signal([providing_args=list]) |
|
192 |
|
193 All signals are :class:`django.dispatch.Signal` instances. The |
|
194 ``providing_args`` is a list of the names of arguments the signal will provide |
|
195 to listeners. |
|
196 |
|
197 For example: |
|
198 |
|
199 .. code-block:: python |
|
200 |
|
201 import django.dispatch |
|
202 |
|
203 pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) |
|
204 |
|
205 This declares a ``pizza_done`` signal that will provide receivers with |
|
206 ``toppings`` and ``size`` arguments. |
|
207 |
|
208 Remember that you're allowed to change this list of arguments at any time, so getting the API right on the first try isn't necessary. |
|
209 |
|
210 Sending signals |
|
211 --------------- |
|
212 |
|
213 There are two ways to send send signals in Django. |
|
214 |
|
215 .. method:: Signal.send(sender, **kwargs) |
|
216 .. method:: Signal.send_robust(sender, **kwargs) |
|
217 |
|
218 To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`. |
|
219 You must provide the ``sender`` argument, and may provide as many other keyword |
|
220 arguments as you like. |
|
221 |
|
222 For example, here's how sending our ``pizza_done`` signal might look: |
|
223 |
|
224 .. code-block:: python |
|
225 |
|
226 class PizzaStore(object): |
|
227 ... |
|
228 |
|
229 def send_pizza(self, toppings, size): |
|
230 pizza_done.send(sender=self, toppings=toppings, size=size) |
|
231 ... |
|
232 |
|
233 Both ``send()`` and ``send_robust()`` return a list of tuple pairs |
|
234 ``[(receiver, response), ... ]``, representing the list of called receiver |
|
235 functions and their response values. |
|
236 |
|
237 ``send()`` differs from ``send_robust()`` in how exceptions raised by receiver |
|
238 functions are handled. ``send()`` does *not* catch any exceptions raised by |
|
239 receivers; it simply allows errors to propagate. Thus not all receivers may |
|
240 be notified of a signal in the face of an error. |
|
241 |
|
242 ``send_robust()`` catches all errors derived from Python's ``Exception`` class, |
|
243 and ensures all receivers are notified of the signal. If an error occurs, the |
|
244 error instance is returned in the tuple pair for the receiver that raised the error. |
|
245 |
|
246 Disconnecting signals |
|
247 ===================== |
|
248 |
|
249 .. method:: Signal.disconnect([receiver=None, sender=None, weak=True, dispatch_uid=None]) |
|
250 |
|
251 To disconnect a receiver from a signal, call :meth:`Signal.disconnect`. The |
|
252 arguments are as described in :meth:`.Signal.connect`. |
|
253 |
|
254 The *receiver* argument indicates the registered receiver to disconnect. It may |
|
255 be ``None`` if ``dispatch_uid`` is used to identify the receiver. |