Ruhshan
Ruhshan

Reputation: 121

Detect change in apps and user who made changes by a separate app Django.

I'm trying to create an app, say activitylogapp in the project that detects if in another app say Employeeapp some models are changed/updated and keep a log. I don't want touch Employeeapp. I can access changes by using signals in the models.py of activitylodapp. By this:

from django.db.models.signals import post_save
from anotherapp.models import Employee
from django.dispatch import receiver

@receiver(post_save, sender=Employee)
def save_handler(sender, instance, created, **kswargs):
    "Things I want to do"

The problem is I also want to access which user made these changes, like request.user.username that is used in views.py. Is it possible without explicitly injecting request object from view to activitylog app?

Upvotes: 0

Views: 61

Answers (1)

Art
Art

Reputation: 2335

You can add a primitive middleware into your "activitylogapp" with process_request to store the request.

As for storing the request, I see 2 options:

  1. Ugly but fast to implement. Save the request globally. It shouldn't affect anything as you get a fresh new cloned thread for each request, which dies right after the request has been processed.

  2. More sophisticated, without globals. Utilize the fact, that Django signals create weak references to their receiver functions. So you can attach save_handler to the request itself, and they will get GC-ed together in the end. Something like that:

    class MyMiddleware(object):
    
        def process_request(request):
    
            def save_handler(sender, instance, created, **kswargs):
                user = request.user
                "do the stuff you want to do"
    
            # without the following line, the save_handler will be
            # garbage collected right away since nothing references it
            request._my_save_handler_instance = save_handler 
    
            post_save.register(save_handler, ...)
    

Upvotes: 1

Related Questions