Django: Populate user ID when saving a model Django: Populate user ID when saving a model django django

Django: Populate user ID when saving a model


If you want something that will work both in the admin and elsewhere, you should use a custom modelform. The basic idea is to override the __init__ method to take an extra parameter - request - and store it as an attribute of the form, then also override the save method to set the user id before saving to the database.

class MyModelForm(forms.ModelForm):   def __init__(self, *args, **kwargs):       self.request = kwargs.pop('request', None)       return super(MyModelForm, self).__init__(*args, **kwargs)   def save(self, *args, **kwargs):       kwargs['commit']=False       obj = super(MyModelForm, self).save(*args, **kwargs)       if self.request:           obj.user = self.request.user       obj.save()       return obj


UPDATE 2020-01-02
⚠ The following answer was never updated to the latest Python and Django versions. Since writing this a few years ago packages have been released to solve this problem. Nowadays I highly recommend using django-crum which implements the same technique but has tests and is updated regularly: https://pypi.org/project/django-crum/

The least obstrusive way is to use a CurrentUserMiddleware to store the current user in a thread local object:

current_user.py

from threading import local_user = local()class CurrentUserMiddleware(object):    def process_request(self, request):        _user.value = request.userdef get_current_user():    return _user.value

Now you only need to add this middleware to your MIDDLEWARE_CLASSES after the authentication middleware.

settings.py

MIDDLEWARE_CLASSES = (    ...    'django.contrib.auth.middleware.AuthenticationMiddleware',    ...    'current_user.CurrentUserMiddleware',    ...)

Your model can now use the get_current_user function to access the user without having to pass the request object around.

models.py

from django.db import modelsfrom current_user import get_current_userclass MyModel(models.Model):    created_by = models.ForeignKey('auth.User', default=get_current_user)

Hint:

If you are using Django CMS you do not even need to define your own CurrentUserMiddleware but can use cms.middleware.user.CurrentUserMiddleware and the cms.utils.permissions.get_current_user function to retrieve the current user.


Daniel's answer won't work directly for the admin because you need to pass in the request object. You might be able to do this by overriding the get_form method in your ModelAdmin class but it's probably easier to stay away from the form customisation and just override save_model in your ModelAdmin.

def save_model(self, request, obj, form, change):    """When creating a new object, set the creator field.    """    if not change:        obj.creator = request.user    obj.save()