[Fixed]-Make the user in a model default to the current user


Since you need to get the currently logged in user from a request object you cannot get it in the model’s save-method,but you can eg override the model admin’s save_model-method:

class MyAdmin(admin.ModelAdmin):
    def save_model(self, request, instance, form, change):
        user = request.user 
        instance = form.save(commit=False)
        if not change or not instance.created_by:
            instance.created_by = user
        instance.modified_by = user
        return instance


You have to override get_changeform_initial_data method in your model Admin class in admin.py as follows:

# admin.py

class ClientDetailsAdmin(admin.ModelAdmin):
    def get_changeform_initial_data(self, request):
        get_data = super(ClientDetailsAdmin, self).get_changeform_initial_data(request)
        get_data['created_by'] = request.user.pk
        return get_data

admin.site.register(ClientDetails, ClientDetailsAdmin)

In such way you obtain the most elegant solution since the created_by field is filed up when you create new record.


I had a similar issue recently, this is from my views.py file

def CircleAdd(request):

    form = CircleAddForm(request.POST)

    if form.is_valid():

        Circle = form.save(commit=False)
        Circle.Author = request.user
        Circle = Circle.save()

And then I had a form for the ‘circles’ model, which was just a wrapper really (forms.py)

class CircleAddForm(ModelForm):
    class Meta:
        model = Circle

Remember to import the form in your view!

Edit: not even sure if you even need to bother with the separate form, the key bit is the fake commit, followed by the real



Building on the accepted answer, if you’re looking to do this with Class Based views, you can follow the instructions in the docs, overriding the form_valid() method on the class view:

# views.py

from django.views.generic.edit import CreateView

class CreateClient(CreateView):
    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super(CreateClient, self).form_valid(form)


Normal modelfields have a default argument. But ForeignKeys do not as far as I know, so I guess you need to work with a post_save signal.



I found:

from django.db import models
from django.contrib.auth.models import User

class CurrentUserField(models.ForeignKey):
    def __init__(self, **kwargs):
        super(CurrentUserField, self).__init__(User, null=True, **kwargs)

    def contribute_to_class(self, cls, name):
        super(CurrentUserField, self).contribute_to_class(cls, name)
        registry = registration.FieldRegistry()
        registry.add_field(cls, self)

class ClientDetails(models.Model):
    created_by = CurrentUserField()

from here. But isn’t there an easier way?

Leave a comment