You don't have access to the request (and therefore the current user) from your model. This is by design in Django.
The more straightforward approaches are less DRY but more explicit:
- Create a reusable
ModelForm
that automatically saves the user to the model when the form is saved
- Create reusable class based
View
that automatically saves the user to your model
- Create or a reuseable
ModelAdmin
that automatically saves the user to the model (or this answer)
But if you want truly transparent saving of creator/modifier, that is more DRY but less explicit, you can:
- Write some middleware that transparently saves the user information to the model on save using signals
- Alternatively you could use a threadlocal to set the current user via a more simple piece of middleware and then access that threadlocal again in your models
save()
method. You need to be careful with threadlocals
This is the first of the more transparent options:
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 'created_by' in instance._meta.fields and not instance.created_by:
instance.created_by = user
if 'modified_by' in instance._meta.fields:
instance.modified_by = user