Skip to content

Commit e8ab2bb

Browse files
Fixed #36600 -- Clarified the use cases for dispatch_uid in signal connection.
Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
1 parent 12bb16d commit e8ab2bb

1 file changed

Lines changed: 27 additions & 16 deletions

File tree

docs/topics/signals.txt

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ Now, our ``my_receiver`` function will be called each time a request finishes.
172172

173173
The :meth:`~django.apps.AppConfig.ready` method may be executed more than
174174
once during testing, so you may want to :ref:`guard your signals from
175-
duplication <preventing-duplicate-signals>`, especially if you're planning
176-
to send them within tests.
175+
duplication <preventing-duplicate-signals>` if your receiver is a bound
176+
method on an instance that may be recreated.
177177

178178
.. _connecting-to-specific-signals:
179179

@@ -211,20 +211,31 @@ each particular signal.
211211
Preventing duplicate signals
212212
----------------------------
213213

214-
In some circumstances, the code connecting receivers to signals may run
215-
multiple times. This can cause your receiver function to be registered more
216-
than once, and thus called as many times for a signal event. For example, the
217-
:meth:`~django.apps.AppConfig.ready` method may be executed more than once
218-
during testing. More generally, this occurs everywhere your project imports the
219-
module where you define the signals, because signal registration runs as many
220-
times as it is imported.
221-
222-
If this behavior is problematic (such as when using signals to
223-
send an email whenever a model is saved), pass a unique identifier as
224-
the ``dispatch_uid`` argument to identify your receiver function. This
225-
identifier will usually be a string, although any hashable object will
226-
suffice. The end result is that your receiver function will only be
227-
bound to the signal once for each unique ``dispatch_uid`` value::
214+
When ``dispatch_uid`` is not provided, Django identifies each receiver using
215+
its Python object identity and registers it only once. For module-level
216+
functions, static methods, and class methods, the identity is stable, so
217+
connecting the same receiver more than once has no effect::
218+
219+
def my_handler(sender, **kwargs): ...
220+
221+
222+
my_signal.connect(my_handler) # Running this code again is a no-op.
223+
224+
Bound methods, which take a ``self`` argument, are different. Their identity
225+
is tied to the specific instance, so connecting the same method from a new
226+
instance registers it as an additional receiver::
227+
228+
def connect_signals():
229+
backend = Backend()
230+
my_signal.connect(backend.my_handler) # A distinct receiver.
231+
232+
233+
connect_signals() # Running this code again registers another receiver.
234+
235+
When using a bound method as a receiver, multiple registrations can be
236+
prevented by supplying a unique ``dispatch_uid``. This identifier will usually
237+
be a string, although any hashable object will suffice. The receiver will only
238+
be bound to the signal once for each unique ``dispatch_uid`` value::
228239

229240
from django.core.signals import request_finished
230241

0 commit comments

Comments
 (0)