profile_update_form does not update field correctly, print logs suggest issue with redundant if statement

14 views Asked by At

Submitting an update profile form is expected to post and return an updated username on the same page in localhost:8000/profile/

Instead, the page refreshes returning the unchanged username.

Debugging steps.

  1. The view is set up like so with print logs to identify the problem area.
# users/views/profile.py

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import update_session_auth_hash
from ..forms import ProfileUpdateForm, CustomPasswordChangeForm
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin

import logging

logger = logging.getLogger(__name__)

class ProfileView(LoginRequiredMixin, View):
    template_name = 'my_profile.html'

    def get(self, request, *args, **kwargs):

        print('getting...')
        profile_update_form = ProfileUpdateForm(instance=request.user)
        password_form = CustomPasswordChangeForm(user=request.user)
        context = {
            'profile_update_form': profile_update_form,
            'password_form': password_form,
        }
        return render(request, self.template_name, context)

    def post(self, request, *args, **kwargs):        
        profile_update_form = ProfileUpdateForm(instance=request.user)
        password_form = CustomPasswordChangeForm(user=request.user)
        print('posting...')
        print(request.POST) # identifies correct form input...
        print('user')
        print(request.user) # identifies current username
        print('username') 
        print(request.user.username) # identifies current username
        print('saving...') # printing successfully...

        if 'update_profile' in request. POST: 
            profile_update_form = ProfileUpdateForm(request.POST, instance=request.user)
            print('profile updating...') # seems to become unresponsive around here with no print logs...
            print(profile_update_form)
            
            if profile_update_form.is_valid():
                print('profile is valid')
                profile_update_form.save()
                messages.success(request, 'Your profile has been updated.')
                print("Profile updated")
                print(request.user)
                print(request.user.username)
                return redirect('my_profile')
            else:
                print("Profile not updated")
                print(profile_update_form.errors)
                for field, errors in profile_update_form.errors.items():
                    for error in errors:
                        messages.error(request, f"{field}: {error}")

[...]

    
  1. The template is set up like so (extract). it was previously a crispy form but I am now trying to render it manually:
           <form method="post" action="{% url 'my_profile' %}">
               {% csrf_token %}
               <input type="hidden" name="form_type" value="update_profile">
               <!-- Manually render each field -->
               {% for field in profile_update_form %}
                   <div>
                       <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                       {{ field }}
                       {% if field.help_text %}
                           <small style="color: grey;">{{ field.help_text }}</small>
                       {% endif %}
                       {% for error in field.errors %}
                           <div style="color: red;">{{ error }}</div>
                       {% endfor %}
                   </div>
               {% endfor %}
               <button type="submit" class="btn btn-primary">Update Profile</button>
           </form>
1

There are 1 answers

0
Laurie Crean On

the if statement needed to call the form correctly.

changing to correct form type listener allowed the form to submit successfully.

if request. POST.get('form_type') == 'update_profile' 
# locates the form with hidden input: <input type="hidden" name="form_type" value="update_profile"> 
# ...proceeds to save as expected 

this even works with crispy forms, it just needed to be located with the hidden input

<form method="post" action="{% url 'my_profile' %}">
    {% csrf_token %}

     <!-- ProfileView class finds the following hidden input with IF request line 41: if POST.get('form_type') == 'update_profile' -->
    <input type="hidden" name="form_type" value="update_profile"> 

    {{ profile_update_form|crispy }}  
    <button type="submit" class="btn btn-primary">Update Profile</button>
</form>

enter image description here