From b9172e90eb7eb379be994cd63c9705b7f2be6a1a Mon Sep 17 00:00:00 2001 From: Amar <100243770+aadeina@users.noreply.github.com> Date: Fri, 6 Mar 2026 06:17:30 +0000 Subject: [6.0.x] Fixed #36600 -- Clarified the use cases for dispatch_uid in signal connection. Co-authored-by: Jacob Walls Backport of e8ab2bb83fc6d3c0f5d998d1a41ebaebacaa1a28 from main. --- docs/topics/signals.txt | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 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 `, especially if you're planning - to send them within tests. + duplication ` 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. - -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:: +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:: + + 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 -- cgit v1.3