Skip to content

Instantly share code, notes, and snippets.

@mindlace
Created October 19, 2012 13:43
Show Gist options
  • Star 38 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save mindlace/3918300 to your computer and use it in GitHub Desktop.
Save mindlace/3918300 to your computer and use it in GitHub Desktop.
Add user created/modified to every model
"""Add user created_by and modified_by foreign key refs to any model automatically.
Almost entirely taken from https://github.com/Atomidata/django-audit-log/blob/master/audit_log/middleware.py"""
from django.db.models import signals
from django.utils.functional import curry
class WhodidMiddleware(object):
def process_request(self, request):
if not request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
if hasattr(request, 'user') and request.user.is_authenticated():
user = request.user
else:
user = None
mark_whodid = curry(self.mark_whodid, user)
signals.pre_save.connect(mark_whodid, dispatch_uid = (self.__class__, request,), weak = False)
def process_response(self, request, response):
signals.pre_save.disconnect(dispatch_uid = (self.__class__, request,))
return response
def mark_whodid(self, user, sender, instance, **kwargs):
if not getattr(instance, 'created_by_id', None):
instance.created_by = user
if hasattr(instance,'modified_by_id'):
instance.modified_by = user
@matt-e-king
Copy link

Brilliant. Thanks!

@anujism
Copy link

anujism commented Jul 13, 2016

How to use this?

@xuzhe0628
Copy link

Fantastic. It really helps me a lot.

@lukik
Copy link

lukik commented Oct 22, 2016

October 2016. With Django==1.10.2 and djangorestframework==3.4.7 it still works with no modification whatsoever. Thanks.

@dariushazimi
Copy link

Can you provide an example to use within a model?

@stevelacey
Copy link

stevelacey commented Feb 14, 2017

I keep coming back to this gist on projects, it's a good DRY solution to the problem.

If anyone needs it to also work with Django REST Framework (which uses its own auth system), you can manually fire the DRF backends you use there by swapping the user = lines above out for something like this which tries the same but falls back to DRF if unauthed:

from rest_framework import authentication

try:
    user = request.user
    if not user.is_authenticated():
        auth = authentication.BasicAuthentication().authenticate(request)
        if auth:
            user = auth[0]
        else:
            user = None
except (authentication.exceptions.AuthenticationFailed, KeyError):
    user = None

Modify to suit your needs aka your backends which are hopefully not basic auth – if anyone can be bothered I imagine this can be improved to pull the backends you use out of settings.py without too much difficulty.

@sdreher
Copy link

sdreher commented Mar 1, 2018

Update for Django 2.0, doc

from django.db.models import signals
from django.utils.functional import curry


class WhodidMiddleware(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if hasattr(request, 'user') and request.user.is_authenticated:
                user = request.user
            else:
                user = None

            mark_whodid = curry(self.mark_whodid, user)
            signals.pre_save.connect(
                mark_whodid,
                dispatch_uid=(self.__class__, request,),
                weak=False)

        response = self.get_response(request)

        signals.pre_save.disconnect(dispatch_uid=(self.__class__, request,))

        return response

    def mark_whodid(self, user, sender, instance, **kwargs):
        if not getattr(instance, 'created_by_id', None):
            instance.created_by = user
        if hasattr(instance, 'modified_by_id'):
            instance.modified_by = user

@romaintha
Copy link

I am not sure that this method is thread safe. According to the signal source code, Signal are shared by threads. Or am I missing something?

@purushottam-bitle
Copy link

Can someone explain How to use above code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment