Create single decorator for multiple `mongoengine signal`

Viewed 52

I am experimenting with mongoengine. I want to audit each successful event(add/update/delete) on mongo.

For that I have created a decorator using mongoengine signal like below

from mongoengine import signals, Document, StringField
def handler(event):

    def decorator(fn):
        def apply(cls):
            event.connect(fn, sender=cls)
            return cls

        fn.apply = apply
        return fn

    return decorator


@handler(signals.post_save)
def event_handler(sender, document, **kwargs):
    """Handle your event here"""
    #do some stuff
    print("Event successfully handled")

#@handler(signals.post_delete)
#def event_handler(sender, document, **kwargs):
#    """Handle your event here"""
#    #do some stuff
#    print("Event successfully handled")


@event_handler.apply
class SampleObject(Document):
    field1 = StringField()
    field2 = StringField()
    field3 = StringField()
    field4 = StringField()

with the above code I am able to handle only save event with same name as event_handler.

I want to handle event for save, delete, update with same decorator event_handler.apply.

Is it possible? or I have to handle separately with diff name like save_event_handler.apply and handler separately for save or delete_event_handler.apply and handle separately for delete and so on?

2 Answers

One approach would be to override the save(), update() and delete() methods of the mongoengine Document class and extend your data objects with this overridden class. You can then write your custom logic of handling signals in separate method and use it in those overridden methods along with the existing logic of what they intend to do respectively. Let me know if you want an example code for it.

For deletion you need to handle it separately using pre_delete or post_delete signal.

For updating you can handle it in the same event_handler function by checking if document has an id. Note that there are no signals for .update() method, you will to use .save() instead.

@handler(signals.post_save)
def event_handler(sender, document, **kwargs):
    if document.id:
        print("This is an update operation")
Related