@@ -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.
211211Preventing 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