[Django]-How to assign currently logged in user as default value for a model field?

12👍

✅

No, you can’t do it this way. Django (and Python) has pretty much zero global values, and that’s a Good Thing(tm). Normally you get the current user in the view(request) with request.user. You can then pass that as a param to various methods/functions, but trying to set a global user will only lead to tears in a multi-threaded environment.

There should be a bumper sticker that says, Globals are Evil. This will give you a good idea about my Number One problem with PHP.

40👍

If you want to achieve this within the admin interface, you can use the save_model method. See below an example:

class List(models.Model):
    title = models.CharField(max_length=64)
    author = models.ForeignKey(User)

class ListAdmin(admin.ModelAdmin):
    fields = ('title',)
    def save_model(self, request, obj, form, change):
        obj.author = request.user
        obj.save()

6👍

SOLVED:
I will use an example, but the important part is the funciton on the views.py.
User is automatically available by django.
Note the ‘autor’ model field has a ForeignKey to the ‘User’.
In the ‘def form_valid’ below I assign the currently logged in user as the default value.

If this is your model:

class ProspectoAccion(models.Model):
"""
Model representing a comment against a blog post.
"""
    descripcion = models.TextField(max_length=1000)
    autor = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    accion_date = models.DateTimeField(auto_now_add=True)
    prospecto= models.ForeignKey(Prospecto, on_delete=models.CASCADE)
    tipo_accion = models.ForeignKey('Accion', on_delete=models.SET_NULL, null=True)

And you have a class based view, do the following:

class ProspectoAccionCreate(LoginRequiredMixin, CreateView):
"""
Form for adding una acción. Requires login (despues poner)
"""
    model = ProspectoAccion
    fields = ['tipo_accion','descripcion',]

    def form_valid(self, form):

        #Add logged-in user as autor of comment THIS IS THE KEY TO THE SOLUTION
        form.instance.autor = self.request.user

        # Call super-class form validation behaviour
        return super(ProspectoAccionCreate, self).form_valid(form)

HERE IS AN EXAMPLE FROM THE DOCUMENTATION:
https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-editing/#models-and-request-user

1👍

If use ModelForm, the following will fill a default value for a special field. such as, owner filed is a charfield for user’s name

def fillview(request):
    instance = YourModel(owner=request.user.username)
    form = YourModelForm(instance=instance)

    if request.method == 'POST':
        form = YourModelForm(request.POST, request.FILES)
        if form.is_valid():
            pass
            return render(request, 'success.html')

    return render(request, 'fill.html', {'form': form})

When logged in, you could see owner filed is current user’s name.

0👍

The highest-voted answer works, but does not fill out the form field for you.

If you do want the form field to be pre-filled when creating a new object in the admin, set the field’s initial value:

class TaskAdmin(admin.ModelAdmin):
    ...

    def get_form(self, request, *args, **kwargs):
        form_class = super().get_form(request, *args, **kwargs)
        form_class.base_fields['created_by'].initial = request.user
        return form_class
    
    ...

Another option would be to extend get_changeform_initial() as mentioned here (note this only gets called when creating a new object).

-2👍

By default, Django already creates a “created_by” attribute. You don’t need to create your own.

If you nonetheless need to save this information separately to, let’s say, have the possibility to change the user later on without affecting the original creator value, then you could override the save function to retrieve the value that Django assigns by default to “created_user”:

class Application(models.Model):
    property = models.ForeignKey(Property, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='applications', editable=False, null=True)
    ...

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if not self.user:
            self.user = self.created_by
            super(Application, self).save(*args, **kwargs)

Leave a comment