summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/topics/signals.txt41
1 files changed, 26 insertions, 15 deletions
diff --git a/docs/topics/signals.txt b/docs/topics/signals.txt
index 4d32c55a2b..0c353ba8bd 100644
--- a/docs/topics/signals.txt
+++ b/docs/topics/signals.txt
@@ -172,8 +172,8 @@ Now, our ``my_callback`` function will be called each time a request finishes.
The :meth:`~django.apps.AppConfig.ready` method may be executed more than
once during testing, so you may want to :ref:`guard your signals from
- duplication <preventing-duplicate-signals>`, especially if you're planning
- to send them within tests.
+ duplication <preventing-duplicate-signals>` if your receiver is a bound
+ method on an instance that may be recreated.
.. _connecting-to-specific-signals:
@@ -211,20 +211,31 @@ each particular signal.
Preventing duplicate signals
----------------------------
-In some circumstances, the code connecting receivers to signals may run
-multiple times. This can cause your receiver function to be registered more
-than once, and thus called as many times for a signal event. For example, the
-:meth:`~django.apps.AppConfig.ready` method may be executed more than once
-during testing. More generally, this occurs everywhere your project imports the
-module where you define the signals, because signal registration runs as many
-times as it is imported.
+When ``dispatch_uid`` is not provided, Django identifies each receiver using
+its Python object identity and registers it only once. For module-level
+functions, static methods, and class methods, the identity is stable, so
+connecting the same receiver more than once has no effect::
-If this behavior is problematic (such as when using signals to
-send an email whenever a model is saved), pass a unique identifier as
-the ``dispatch_uid`` argument to identify your receiver function. This
-identifier will usually be a string, although any hashable object will
-suffice. The end result is that your receiver function will only be
-bound to the signal once for each unique ``dispatch_uid`` value::
+ def my_handler(sender, **kwargs): ...
+
+
+ my_signal.connect(my_handler) # Running this code again is a no-op.
+
+Bound methods, which take a ``self`` argument, are different. Their identity
+is tied to the specific instance, so connecting the same method from a new
+instance registers it as an additional receiver::
+
+ def connect_signals():
+ backend = Backend()
+ my_signal.connect(backend.my_handler) # A distinct receiver.
+
+
+ connect_signals() # Running this code again registers another receiver.
+
+When using a bound method as a receiver, multiple registrations can be
+prevented by supplying a unique ``dispatch_uid``. This identifier will usually
+be a string, although any hashable object will suffice. The receiver will only
+be bound to the signal once for each unique ``dispatch_uid`` value::
from django.core.signals import request_finished