summaryrefslogtreecommitdiff
path: root/parts/django/docs/topics/signals.txt
diff options
context:
space:
mode:
authorNishanth Amuluru2011-01-08 11:20:57 +0530
committerNishanth Amuluru2011-01-08 11:20:57 +0530
commit65411d01d448ff0cd4abd14eee14cf60b5f8fc20 (patch)
treeb4c404363c4c63a61d6e2f8bd26c5b057c1fb09d /parts/django/docs/topics/signals.txt
parent2e35094d43b4cc6974172e1febf76abb50f086ec (diff)
downloadpytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.gz
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.bz2
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.zip
Added buildout stuff and made changes accordingly
--HG-- rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => parts/django/Django.egg-info/dependency_links.txt rename : taskapp/models.py => parts/django/django/conf/app_template/models.py rename : taskapp/tests.py => parts/django/django/conf/app_template/tests.py rename : taskapp/views.py => parts/django/django/conf/app_template/views.py rename : taskapp/views.py => parts/django/django/contrib/gis/tests/geo3d/views.py rename : profile/management/__init__.py => parts/django/tests/modeltests/delete/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/files/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/invalid_models/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/m2m_signals/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/model_package/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/commands/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/models.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/delete_regress/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/file_storage/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/max_lengths/__init__.py rename : profile/forms.py => pytask/profile/forms.py rename : profile/management/__init__.py => pytask/profile/management/__init__.py rename : profile/management/commands/seed_db.py => pytask/profile/management/commands/seed_db.py rename : profile/models.py => pytask/profile/models.py rename : profile/templatetags/user_tags.py => pytask/profile/templatetags/user_tags.py rename : taskapp/tests.py => pytask/profile/tests.py rename : profile/urls.py => pytask/profile/urls.py rename : profile/utils.py => pytask/profile/utils.py rename : profile/views.py => pytask/profile/views.py rename : static/css/base.css => pytask/static/css/base.css rename : taskapp/tests.py => pytask/taskapp/tests.py rename : taskapp/views.py => pytask/taskapp/views.py rename : templates/base.html => pytask/templates/base.html rename : templates/profile/browse_notifications.html => pytask/templates/profile/browse_notifications.html rename : templates/profile/edit.html => pytask/templates/profile/edit.html rename : templates/profile/view.html => pytask/templates/profile/view.html rename : templates/profile/view_notification.html => pytask/templates/profile/view_notification.html rename : templates/registration/activate.html => pytask/templates/registration/activate.html rename : templates/registration/activation_email.txt => pytask/templates/registration/activation_email.txt rename : templates/registration/activation_email_subject.txt => pytask/templates/registration/activation_email_subject.txt rename : templates/registration/logged_out.html => pytask/templates/registration/logged_out.html rename : templates/registration/login.html => pytask/templates/registration/login.html rename : templates/registration/logout.html => pytask/templates/registration/logout.html rename : templates/registration/password_change_done.html => pytask/templates/registration/password_change_done.html rename : templates/registration/password_change_form.html => pytask/templates/registration/password_change_form.html rename : templates/registration/password_reset_complete.html => pytask/templates/registration/password_reset_complete.html rename : templates/registration/password_reset_confirm.html => pytask/templates/registration/password_reset_confirm.html rename : templates/registration/password_reset_done.html => pytask/templates/registration/password_reset_done.html rename : templates/registration/password_reset_email.html => pytask/templates/registration/password_reset_email.html rename : templates/registration/password_reset_form.html => pytask/templates/registration/password_reset_form.html rename : templates/registration/registration_complete.html => pytask/templates/registration/registration_complete.html rename : templates/registration/registration_form.html => pytask/templates/registration/registration_form.html rename : utils.py => pytask/utils.py
Diffstat (limited to 'parts/django/docs/topics/signals.txt')
-rw-r--r--parts/django/docs/topics/signals.txt255
1 files changed, 255 insertions, 0 deletions
diff --git a/parts/django/docs/topics/signals.txt b/parts/django/docs/topics/signals.txt
new file mode 100644
index 0000000..35e111d
--- /dev/null
+++ b/parts/django/docs/topics/signals.txt
@@ -0,0 +1,255 @@
+=======
+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.