Populate logged on username in a model in a form

Hi there,

I have a very simple requirement to populate a field in a form with a current username.

I am a django beginner hence my code might not look the best.

models.py

class PII(models.Model):
    username = models.CharField(max_length=128, editable=False)
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)
    created_on = models.DateField(auto_now_add=True)

    def get_absolute_url(self):
        return reverse('page:index')

and my views.py

class PIIView(CreateView):
    model = PII
    fields = '__all__'

    def get_context_data(self, **kwargs):
        context = super(PIIView, self).get_context_data(**kwargs)
        context['username'] = self.request.user
        return context

I have pulled it from SO but it does not populate the username:
image

I have seen a similar topic “assign username to field in models.py” however I am pretty sure it will not work in my case, because the table in question is on a separate database and django does not allow FKs between databases.

Is there a way for django to be aware of which user is logged on and filling in that field for me?

Thanks

here self.request.user is a object of user model instance if you want username than use self.request.user.username also you can access any field of user model like self.request.user.first_name, self.request.user.email, etc.

Thanks, I have changed it to user.username but it did not work. Might it be that there’s something wrong in the class based view?

Just checked and I am logged on as admin.

Can you share how you are accessing these context data within template

ummm, I am not, I don’t think?

                    <form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
                        {% csrf_token %}
                        {% include 'app/form-template.html' %}
                        <div class="form-group">
                            <div class="col-sm-offset-2 col-sm-10">
                                <button type="submit" class="btn btn-success">Submit</button>
                            </div>
                        </div>
                    </form>

and that’s form-template.html

{% for field in form %}
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <span class="text-danger small">{{ field.errors }}</span>
        </div>
        <label class="control-label col-sm-2">{{ field.label_tag }}</label>
        <div class="col-sm-10">{{ field }}</div>
    </div>
{% endfor %}

it looks like this:

image

Granted, this is a rough sketch, but I don’t even need the user to be aware of the username being populated, can this work this way?

This part here sends the context data to your template i.e if you access {{username}} in template you will get it rendered however it does not effect your form try it.

I am not sure I understand this bit, how can I try it?

Just put {{username}} in your template save it and reload username will be printed.
If you want to work around the form you need to override get_form() method instead of get_context_data()

ok, I will read up on the get_form() method. thanks

The first thing I’d check is to see whether you’re actually logged on to Django when you’re accessing that page. The page is not protected by LoginRequiredMixin, so you may be accessing it anonymously.

Also, it may be easier to add a print statement or two in that function to see what the view thinks the situation is at that point. Perhaps adding both print(self.request.user) and print(self.request.user.username) may provide some insight.

Hi Kevin,

Thank you for replying. I have managed to partially solve it by doing the following:

forms.py

class PIIForm(forms.ModelForm):

    class Meta:
        model = PII
        fields = '__all__'

views.py

class PIIView(View):
    form_class = PIIForm
    template_name = 'app/pii_form.html'

    def get(self, request):
        form = self.form_class(initial={'username': get_user(request)})
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = self.form_class(request.POST)

        if form.is_valid():
            f = form.save(commit=False)
            f.save()
            return redirect('warszawa:index')
        return render(request, self.template_name, {'form': form})

However one thing I cannot solve which is make the username field not editable by the user. When I use fields.disabled it does not get passed by POST request, when I use fields.readonly it does nothing at all.

However my initial question, which is to populate the logged on username works.

Alternatively I have managed to do it without ModelForm entirely:

 class PIIView(CreateView):
     model = PII
     fields = '__all__'

     def get_initial(self):
         return {"username": self.request.user.username}

With the same caveats as above re: making the field non editable.

I’m not sure I understand what the issue is here. If it’s not editable, why should you care if it’s not being returned by the post?