Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:djangoadv [2014/06/02 11:35] alfred [Customizing authorization] |
fw:djangoadv [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 59: | Línea 59: | ||
| ===== Signals ===== | ===== Signals ===== | ||
| + | ==== Signals in Django ==== | ||
| + | Django provides a way of intercept special notifications... | ||
| + | * ''django.db.models.signals.pre_save'' & ''django.db.models.signals.post_save'', sent before or after a model’s save() method is called. | ||
| + | * ''django.db.models.signals.pre_delete'' & ''django.db.models.signals.post_delete'', sent before or after a model’s delete() method or queryset’s delete() method is called. | ||
| + | * ''django.db.models.signals.m2m_changed'', sent when a ManyToManyField on a model is changed. | ||
| + | * ''django.core.signals.request_started'' & ''django.core.signals.request_finished'', sent when Django starts or finishes an HTTP request. | ||
| + | There are [[https://docs.djangoproject.com/en/dev/ref/signals/|ohters]] like ''pre_init'', ''class_prepared'', ''pre_migrate'', ''pre_syncdb'', ''got_request_exception'', ''connection_created''... | ||
| + | ==== Connecting signals ==== | ||
| + | |||
| + | The way to intercept a signal is using the ''connect()'' function or the ''receiver()'' decorator: | ||
| + | <code python> | ||
| + | def my_callback(sender, **kwargs): | ||
| + | print("Request finished!") | ||
| + | # ....... | ||
| + | from django.core.signals import request_finished | ||
| + | request_finished.connect(my_callback) | ||
| + | # ....... | ||
| + | from django.core.signals import request_finished | ||
| + | from django.dispatch import receiver | ||
| + | @receiver(request_finished) | ||
| + | def my_callback(sender, **kwargs): | ||
| + | print("Request finished!") | ||
| + | </code> | ||
| + | |||
| + | The function ''Signal.connect'' has the next argument: | ||
| + | <code python> | ||
| + | Signal.connect(receiver[, sender=None, weak=True, dispatch_uid=None]) | ||
| + | </code> | ||
| + | Its arguments mean: | ||
| + | * Receiver argument is a function defined as: ''def my_callback(sender, <nowiki>**kwargs</nowiki>)''. | ||
| + | * Sender argument concretes a sender class. | ||
| + | * Weak argument avoid Django storing signal handlers as weak references, which is done 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. | ||
| + | * dispatch_uid, its an unique identifier for a signal receiver in cases where duplicate signals may be sent. | ||
| + | |||
| + | <code python> | ||
| + | from myapp.models import MyModel | ||
| + | @receiver(pre_save, sender=MyModel) | ||
| + | def my_handler(sender, **kwargs): | ||
| + | ... | ||
| + | request_finished.connect(my_callback, dispatch_uid="my_unique_identifier") | ||
| + | </code> | ||
| + | |||
| + | ==== Defining and sending signals ==== | ||
| + | Signals are ''django.dispatch.Signal([providing_args=list])'' instances. ''providing_args'' is a list of the names of arguments the signal will provide to listeners. To declare a ''pizza_done'' signal which provides receivers with toppics and size arguments: | ||
| + | <code python> | ||
| + | import django.dispatch | ||
| + | pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) | ||
| + | </code> | ||
| + | |||
| + | To send a signal, call either ''Signal.send()'' or ''Signal.send_robust()''. Both return a list of tuple pairs ''[(receiver, response), ... ]''. They differ in how exceptions raised by receiver functions. ''send()'' does not catch any exceptions raised by receivers; it simply allows errors to propagate. Whereas ''send_robust()'' catches all errors derived from Python’s Exception class, and ensures all receivers are notified of the signal. | ||
| + | <code python> | ||
| + | class PizzaStore(object): | ||
| + | ... | ||
| + | def send_pizza(self, toppings, size): | ||
| + | pizza_done.send(sender=self.__class__, toppings=toppings, size=size) | ||
| + | </code> | ||
| + | To disconnect a receiver from a signal, call ''Signal.disconnect()''. | ||