Signals are events dispatched by a sender object, any number of receiver objects can subscribe to such events. A signal receiver can subscribe to a specific sender or may receive signals from many senders.
In MongoEngine, signal handling is supported by blinker library, which means you need to install it using pip utility. The mongoengine.signals module has the definitions of following signals −
|pre_init||Called during the creation of a new Document or EmbeddedDocument instance and executed after the constructor arguments have been collected but before any additional processing has been done to them.|
|post_init||Called after all processing of a new Document or EmbeddedDocument instance has been completed.|
|pre_save||Called within save() prior to performing any actions.|
|pre_save_post_validation||Called within save() after validation has taken place but before saving.|
|post_save||Called within save() after most actions (validation, insert/update) have completed successfully. An additional Boolean keyword argument is passed to indicate if the save was an insert or an update.|
|pre_delete||Called within delete() prior to attempting the delete operation.|
|post_delete||Called within delete() upon successful deletion of the record.|
|pre_bulk_insert||Called after validation of the documents to insert, but prior to any data being written.|
|post_bulk_insert||Called after a successful bulk insert operation. An additional Boolean argument, loaded, identifies the contents of documents as either Document instances when True or a list of primary key values for the inserted records if False.|
An event handler function is then attached to Document class. Note that EmbeddedDocument only supports pre/post_init signals. pre/post_save, etc., should be attached to Document’s class only.
You can also use a decorator to quickly create a number of signals and attach them to your Document or EmbeddedDocument subclasses as class decorators.
In the following example, used as demonstration of signal handlers, we also use Python’s standard library module – logging and set the logging level to debug.
from mongoengine import * from mongoengine import signals import logging logging.basicConfig(level=logging.DEBUG)
We then write a document class so that corresponding collection is created in newdb database. Inside the class, two class mehods pre_save() and post_save() methods are defined which are intended to be invoked before and after a document is saved in Author collection.
class Author(Document): name = StringField() def __unicode__(self): return self.name @classmethod def pre_save(cls, sender, document, **kwargs): logging.debug("Pre Save: %s" % document.name) @classmethod def post_save(cls, sender, document, **kwargs): logging.debug("Post Save: %s" % document.name) if 'created' in kwargs: if kwargs['created']: logging.debug("Created") else: logging.debug("Updated")
Both the class methods are defined with arguments for classname, sender object and document with optional list of keyword arguments.
Finally, we register the signal handlers.
signals.pre_save.connect(Author.pre_save, sender=Author) signals.post_save.connect(Author.post_save, sender=Author)
As we create an instance of Document subclass, the console log will show the pre and post save signals being processed by respective event handlers.
Python console reports the log as shown below −
DEBUG:root:Pre Save: Lathkar DEBUG:root:Post Save: Lathkar DEBUG:root:Created