Auto Fill User In Django Form

Viewed 8504

In my project as soon as user signup it is redirected to update view where he has to fill this information.Since the user has also logged in automatically after signup I want that user field to be filled automatically and can't be edited.

models.py

class Userpro(models.Model):
    user = models.OneToOneField(User)
    dob = models.DateField(default=datetime.date.today)
    country = models.CharField(max_length=50, default='')
    qualification = models.CharField(max_length=10, choices=CHO, 
default='No')
    university = models.CharField(max_length=100, default='')
    location = models.CharField(max_length=100, default='')

    def __str__(self):
        return str(self.user)

forms.py

class UserProForm(forms.ModelForm):
    class Meta:
        model = Userpro
        fields = '__all__'

views.py

def update(request):
    if request.method == 'POST':
        form = UserProForm(request.POST or None)
        if form.is_valid():
            form.save()
            return redirect('/')
        else:
            redirect('/')
    else:
        form = UserProForm()
        return render(request, 'app/update.html', {'form': form})

All the required libraries are imported.

3 Answers

I was with the same problem. The solution I've found is very simple. First remove the "user" field in your forms.py

them in views:

if form.is_valid():
    obj = form.save(commit=False)
    obj.user = request.user
    obj.save()

by making this the obj is a saved form (but not commited in database) and them you can manage it like puting the user as the request.user; them save.

notice that obj."the name you put in your models"

You can use widgets for your form. Something like this(code below is not tested).

from django.forms import TextInput


class UserProForm(forms.ModelForm):
    class Meta:
        model = Userpro
        fields = '__all__'
        widgets = {
            'user': TextInput(attrs={'readonly': 'readonly'})
        }

def update(request):
    instance = Userpro.objects.filter(user=request.user).first()
    if request.method == 'POST':
        form = UserProForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return redirect('/')
        else:
            return redirect('/')
    else:
        form = UserProForm(instance=instance)
        return render(request, 'app/update.html', {'form': form})

Edited: we should pass user inside dict like this: form = UserProForm({'user': request.user})

Edited 2: You should find profile object first and then pass it to the form

instance = Userpro.objects.filter(user=request.user).first()
form = UserProForm(request.POST, instance=instance)

I think it will be better if you will use ModelForm with fields that you want to modify and in template show object instance values like that.

from django.forms import TextInput


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = Userprofile
        fields = ('field1', 'field2')

def update(request):
    if request.method == 'POST':
        form = UserProfileForm(request.POST or None)
        if form.is_valid():
            form.save()
            return redirect('/')
        else:
            redirect('/')
    else:
        form = UserProfileForm(user=request.user)
        return render(request, 'app/update.html', {'form': form})


# template
   <form method="post">
        {% csrf_token %}

        <div class="form-row">
            {{ form.field1.errors }}
            {{ form.field1.label_tag }} {{ form.field1 }}
        </div>
        <div class="form-row">
            {{ form.field2.errors }}
            {{ form.field2.label_tag }} {{ form.field2 }}
        </div>
        <div class="form-row">
            {{ form.instance.field3.errors }}
            {{ form.instance.field3.label_tag }} {{ form.instance.field3 }}
        </div>
    </form>
Related