.. .. META INFORMATION OF TRANSLATION .. .. $TranslationStatus: Done, waiting for revision $ .. $OriginalRevision: 14338 $ .. $TranslationAuthors: Robson Mendonça $ .. .. INFO OF THIS FILE (DO NOT EDIT! UPDATED BY SUBVERSION) .. .. $HeadURL$ .. $LastChangedRevision$ .. $LastChangedBy$ .. $LastChangedDate$ .. .. _topics-signals: ================ Sinais (Signals) ================ .. module:: django.dispatch :synopsis: Despachante de Sinal O Django incluí um "dispachador de sinal" que ajuda ao permitir que aplicações dissociadas sejam notificadas quando uma ação ocorre em qualquer lugar do framework. Em resumo, sinais permitem certos *remetentes* notificar um conjunto de *receptores* sobre alguma ação que tenha ocorrido. Eles são especialmente úteis quando muitas peças de código podem estar interessados nos mesmos eventos. O Django fornece um :doc:`conjunto de sinais embutidos ` que deixam o código do usuário ser notificado pelo próprio Django sobre certas ações. Estas incluem algumas notificações úteis: * :data:`django.db.models.signals.pre_save` & :data:`django.db.models.signals.post_save` Enviado antes ou depois que um método de model :meth:`~django.db.models.Model.save` é chamado. * :data:`django.db.models.signals.pre_delete` & :data:`django.db.models.signals.post_delete` Enviado antes ou depois que um método de model :meth:`~django.db.models.Model.delete` é chamado. * :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` Enviado quando o Django inicia ou finaliza uma requisição HTTP. Veja a :doc:`documentação de sinais embutidos ` para uma lista completa, e uma explicação completa de cada sinal. Você também pode `definir e enviar seus próprios sinais`_; veja abaixo. .. _definir e enviar seus próprios sinais: `definindo e enviando sinais`_ Ouvindo sinais ============== Para receber um sinal, você precisa registrar uma função *receptora* que será chamada quando o sinal é enviado. Vamos ver como isto funciona registrando um sinal que é chamado depois de cada requisição HTTP é finalizada. Nós conectaremo-nos ao sinal :data:`~django.core.signals.request_finished`. .. 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: Funções receptoras ------------------ Primeiro, nós precisamos definir uma função receptora. Um receptor pode ser qualquer função Python ou método: .. code-block:: python def my_callback(sender, **kwargs): print "Request finished!" Observe que a função recebe um argumento ``sender``, junto com o argumento coringa (``**kwargs``); todo manipulador de sinal recebe estes argumentos. Nós olharemos o remetente `um pouco depois`_, mas agora olhe o argumento ``**kwargs``. Todos os sinais enviam argumentos nomeados, e podem mudar seus argumentos nomeados a qualquer momento. Neste caso o :data:`~django.core.signals.request_finished`, ele está documentado como se não enviasse argumentos, que significa que poderiámos ser tentados a escrever nosso manipulador do sinal como ``my_callback(sender)``. .. _um pouco depois: `conectando-se a sinais enviados por remetentes específicos`_ Isso poderia estar errado -- de fato, o Django irá lançar um erro se você fizer isso. Isto porque, em qualquer ponto, argumentos poderiam ser adicionados ao sinal, e o receptor deve ser capaz de manipular estes argumentos. .. _connecting-receiver-functions: Conectando funções receptoras ----------------------------- Agora, nós precisaremos conectar nosso receptor ao sinal: .. code-block:: python from django.core.signals import request_finished request_finished.connect(my_callback) Agora, nossa função ``my_callback`` será chamada a cada vez que uma requisição for finalizada. .. admonition:: Onde este código deve ficar? Você poder colocar o código manipulador e de registro de sinal aonde você quiser. Entretanto, você precisará assegurar-se de que o módulo já tenha sido importado anteriormente, para que este manipulador de sinal seja registrado antes que qualquer sinal seja enviado. Isto faz do ``models.py`` de sua aplicação, um bom lugar para colocar o regsitro de manipuladores de sinais. .. _connecting-to-specific-signals: Conectando-se a sinais enviados por remetentes específicos ---------------------------------------------------------- Alguns sinais são enviados muitas vezes, mas você somente é interessado em receber um certo sub-conjunto destes sinais. Por exemplo, considere o sinal :data:`django.db.models.signals.pre_save` enviado antes de um model ser salvo. Na maioria das vezes, você não precisa saber quando *qualquer* model foi salvo -- só quando um model *específico* é salvo. Nestes casos, você pode registrá-lo para receber sinais enviados somente por um remetente em particular. No caso do :data:`django.db.models.signals.pre_save`, o remetente será a classe model que estiver sendo salva, então você pode indicar que você somente quer sinais enviados por algum 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) A função ``my_handler`` somente será chamada quando uma instância de ``MyModel`` for salva. Sinais diferentes usam objetos diferentes como seus remetentes; você precisará consultar a :ref:`documentação de sinais embutidos ` para detalhes de cada sinal em particular. .. _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") Definindo e enviando sinais =========================== Your applications can take advantage of the signal infrastructure and provide its own signals. Defining signals ---------------- .. class:: Signal([providing_args=list]) Todos os sinais são instâncias de :class:`django.dispatch.Signal`. O ``providing_args`` é uma lista de nomes de argumentos que o sinal fornecerá aos ouvintes. Por exemplo: .. code-block:: python import django.dispatch pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) Este declara um sinal ``pizza_done`` que fornecerá aos receptores os argumentos ``toppings`` e ``size``. Lembre-se de que você está autorizado a alterar esta lista de argumentos a qualquer momento, então obter o direito de API, na primeira tentativa, não é necessário. Enviando sinais --------------- There are two ways to send send signals in Django. .. method:: Signal.send(sender, **kwargs) .. method:: Signal.send_robust(sender, **kwargs) Para enviar um sinal, chame :meth:`Signal.send`. Você deve prover o argumento ``sender``, e pode fornecer muitos outros argumentos nomeados conforme sua vontade. Por exemplo, aqui mostramos como nosso envio de sinal ``pizza_done``, pode ficar: .. 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.