diff options
Diffstat (limited to 'parts/django/docs/topics/signals.txt')
-rw-r--r-- | parts/django/docs/topics/signals.txt | 255 |
1 files changed, 0 insertions, 255 deletions
diff --git a/parts/django/docs/topics/signals.txt b/parts/django/docs/topics/signals.txt deleted file mode 100644 index 35e111d..0000000 --- a/parts/django/docs/topics/signals.txt +++ /dev/null @@ -1,255 +0,0 @@ -======= -Signals -======= - -.. module:: django.dispatch - :synopsis: Signal dispatch - -Django includes a "signal dispatcher" which helps allow decoupled applications -get notified when actions occur elsewhere in the framework. In a nutshell, -signals allow certain *senders* to notify a set of *receivers* that some action -has taken place. They're especially useful when many pieces of code may be -interested in the same events. - -Django provides a :doc:`set of built-in signals </ref/signals>` that let user -code get notified by Django itself of certain actions. These include some useful -notifications: - - * :data:`django.db.models.signals.pre_save` & - :data:`django.db.models.signals.post_save` - - Sent before or after a model's :meth:`~django.db.models.Model.save` method - is called. - - * :data:`django.db.models.signals.pre_delete` & - :data:`django.db.models.signals.post_delete` - - Sent before or after a model's :meth:`~django.db.models.Model.delete` - method is called. - - * :data:`django.db.models.signals.m2m_changed` - - Sent when a :class:`ManyToManyField` on a model is changed. - - * :data:`django.core.signals.request_started` & - :data:`django.core.signals.request_finished` - - Sent when Django starts or finishes an HTTP request. - -See the :doc:`built-in signal documentation </ref/signals>` for a complete list, -and a complete explanation of each signal. - -You can also `define and send your own custom signals`_; see below. - -.. _define and send your own custom signals: `defining and sending signals`_ - -Listening to signals -==================== - -To receive a signal, you need to register a *receiver* function that gets -called when the signal is sent by using the -:meth:`.Signal.connect` method: - -.. method:: Signal.connect(receiver, [sender=None, weak=True, dispatch_uid=None]) - - :param receiver: The callback function which will be connected to this - signal. See :ref:`receiver-functions` for more information. - - :param sender: Specifies a particular sender to receive signals from. See - :ref:`connecting-to-specific-signals` for more information. - - :param weak: Django stores signal handlers as weak references by - default. Thus, if your receiver is a local function, it may be - garbage collected. To prevent this, pass ``weak=False`` when you call - the signal's ``connect()`` method. - - :param dispatch_uid: A unique identifier for a signal receiver in cases - where duplicate signals may be sent. See - :ref:`preventing-duplicate-signals` for more information. - -Let's see how this works by registering a signal that -gets called after each HTTP request is finished. We'll be connecting to the -:data:`~django.core.signals.request_finished` signal. - -.. _receiver-functions: - -Receiver functions ------------------- - -First, we need to define a receiver function. A receiver can be any Python -function or method: - -.. code-block:: python - - def my_callback(sender, **kwargs): - print "Request finished!" - -Notice that the function takes a ``sender`` argument, along with wildcard -keyword arguments (``**kwargs``); all signal handlers must take these arguments. - -We'll look at senders `a bit later`_, but right now look at the ``**kwargs`` -argument. All signals send keyword arguments, and may change those keyword -arguments at any time. In the case of -:data:`~django.core.signals.request_finished`, it's documented as sending no -arguments, which means we might be tempted to write our signal handling as -``my_callback(sender)``. - -.. _a bit later: `connecting to signals sent by specific senders`_ - -This would be wrong -- in fact, Django will throw an error if you do so. That's -because at any point arguments could get added to the signal and your receiver -must be able to handle those new arguments. - -.. _connecting-receiver-functions: - -Connecting receiver functions ------------------------------ - -Next, we'll need to connect our receiver to the signal: - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback) - -Now, our ``my_callback`` function will be called each time a request finishes. - -.. admonition:: Where should this code live? - - You can put signal handling and registration code anywhere you like. - However, you'll need to make sure that the module it's in gets imported - early on so that the signal handling gets registered before any signals need - to be sent. This makes your app's ``models.py`` a good place to put - registration of signal handlers. - -.. _connecting-to-specific-signals: - -Connecting to signals sent by specific senders ----------------------------------------------- - -Some signals get sent many times, but you'll only be interested in receiving a -certain subset of those signals. For example, consider the -:data:`django.db.models.signals.pre_save` signal sent before a model gets saved. -Most of the time, you don't need to know when *any* model gets saved -- just -when one *specific* model is saved. - -In these cases, you can register to receive signals sent only by particular -senders. In the case of :data:`django.db.models.signals.pre_save`, the sender -will be the model class being saved, so you can indicate that you only want -signals sent by some model: - -.. code-block:: python - - from django.db.models.signals import pre_save - from myapp.models import MyModel - - def my_handler(sender, **kwargs): - ... - - pre_save.connect(my_handler, sender=MyModel) - -The ``my_handler`` function will only be called when an instance of ``MyModel`` -is saved. - -Different signals use different objects as their senders; you'll need to consult -the :doc:`built-in signal documentation </ref/signals>` for details of each -particular signal. - -.. _preventing-duplicate-signals: - -Preventing duplicate signals ----------------------------- - -In some circumstances, the module in which you are connecting signals may be -imported multiple times. This can cause your receiver function to be -registered more than once, and thus called multiples times for a single signal -event. - -If this behavior is problematic (such as when using signals to -send an e-mail 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. - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback, dispatch_uid="my_unique_identifier") - -Defining and sending signals -============================ - -Your applications can take advantage of the signal infrastructure and provide -its own signals. - -Defining signals ----------------- - -.. class:: Signal([providing_args=list]) - -All signals are :class:`django.dispatch.Signal` instances. The -``providing_args`` is a list of the names of arguments the signal will provide -to listeners. - -For example: - -.. code-block:: python - - import django.dispatch - - pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) - -This declares a ``pizza_done`` signal that will provide receivers with -``toppings`` and ``size`` arguments. - -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. - -Sending signals ---------------- - -There are two ways to send send signals in Django. - -.. method:: Signal.send(sender, **kwargs) -.. method:: Signal.send_robust(sender, **kwargs) - -To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`. -You must provide the ``sender`` argument, and may provide as many other keyword -arguments as you like. - -For example, here's how sending our ``pizza_done`` signal might look: - -.. code-block:: python - - class PizzaStore(object): - ... - - def send_pizza(self, toppings, size): - pizza_done.send(sender=self, toppings=toppings, size=size) - ... - -Both ``send()`` and ``send_robust()`` return a list of tuple pairs -``[(receiver, response), ... ]``, representing the list of called receiver -functions and their response values. - -``send()`` differs from ``send_robust()`` in how exceptions raised by receiver -functions are handled. ``send()`` does *not* catch any exceptions raised by -receivers; it simply allows errors to propagate. Thus not all receivers may -be notified of a signal in the face of an error. - -``send_robust()`` catches all errors derived from Python's ``Exception`` class, -and ensures all receivers are notified of the signal. If an error occurs, the -error instance is returned in the tuple pair for the receiver that raised the error. - -Disconnecting signals -===================== - -.. method:: Signal.disconnect([receiver=None, sender=None, weak=True, dispatch_uid=None]) - -To disconnect a receiver from a signal, call :meth:`Signal.disconnect`. The -arguments are as described in :meth:`.Signal.connect`. - -The *receiver* argument indicates the registered receiver to disconnect. It may -be ``None`` if ``dispatch_uid`` is used to identify the receiver. |