Create a gist now

Instantly share code, notes, and snippets.

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

Brilliant. Thanks!

@anujism
anujism commented Jul 13, 2016

How to use this?

@xuzhe0628

Fantastic. It really helps me a lot.

@lukik
lukik commented Oct 22, 2016 edited

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

@dariushazimi

Can you provide an example to use within a model?

@stevelacey
stevelacey commented Feb 14, 2017 edited

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.

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