Search code examples
djangodjango-viewsdjango-users

Update/Change information of current User instance in ModelForm in Django


How can I edit an User Instance information of a user(first_name, last_name, email) with extending OneToOne Relationship profile page. Below my code is not giving me any error but also not updating my given information in DB for user. The User model is not created by me but I use django.contrib.auth.models.User also I don't want to use UpdateView class from Django. Any help would be appreciated.

Django Version

asgiref==3.3.1
Django==3.1.5
django-crispy-forms==1.10.0
Pillow==8.1.0
pytz==2020.5
sqlparse==0.4.1

Code:

users/forms.py

from django import forms
from django.contrib.auth.models import User
from .models import Profile


class UserUpdateForm(forms.ModelForm):
    first_name = forms.CharField(max_length=30)
    last_name = forms.CharField(max_length=30)
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']


class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['image']

users/views.py

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import UserUpdateForm, ProfileUpdateForm
from django.contrib import messages


@login_required
def profile(request):
    if request.POST == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, "Your profile has been updated !")
            return redirect('profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile)

    context = {
        'title': "Profile",
        'act': 'profile',
        'u_form': u_form,
        'p_form': p_form,
    }
    return render(request, 'users/profile.html', context)

users/profile.html

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %} {{ title }} {% endblock title %}

{% block content %}
    <div class="content-section align-content-center">
        <div class="media py-3">
            <img src="{{ user.profile.image.url }}" alt="" class="rounded-circle img-thumbnail" height="10" width="180">
            <div class="media-body">
                <h2 class="account-heading pl-3">{{ user.get_full_name }}</h2>
                <p class="text-secondary pl-3">{{ user.email }}</p>
            </div>
        </div>
        <form action="" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Profile Info</legend>
                {{ u_form|crispy }}
                {{ p_form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Update</button>
            </div>
        </form>
    </div>
{% endblock %}

Solution

  • SOLVED

    Bug was in below Profile view, I was checking if request.POST == 'POST' which should be as below. As request.POST returns a QuerySet not a string.

    @login_required
    def profile(request):
        if request.method == 'POST':
            u_form = UserUpdateForm(request.POST, instance=request.user)
            p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)
            if u_form.is_valid() and p_form.is_valid():
                u_form.save()
                p_form.save()
                messages.success(request, "Your profile has been updated !")
                return redirect('profile')
        else:
            u_form = UserUpdateForm(instance=request.user)
            p_form = ProfileUpdateForm(instance=request.user.profile)
    
        context = {
            'title': "Profile",
            'act': 'profile',
            'u_form': u_form,
            'p_form': p_form,
        }
        return render(request, 'users/profile.html', context)