I'm maintaining a Django application and have encountered a bug where if a user edits their profile then their password is corrupted; it seems that set_password is not being used and so the password is set to an unencrypted value which is hardcoded in the form. It's not clear how I could change the existing setup to get around this nuisance, and would welcome any suggestions. The update code looks like this:
@login_required
def profile(request):
user = request.user
profile, created = UserProfile.objects.get_or_create(user=user)
if request.method == 'POST':
userform = UserForm(request.POST, instance=user)
profileform = ProfileForm(request.POST, instance=profile)
if profileform.is_valid():
profileform.save()
if userform.is_valid():
userform.save()
return redirect('user_profile_page')
else:
profileform = ProfileForm(instance=profile)
userform = UserForm(instance=user)
render(request, 'profiles/edit_profile.html', {'profileform': profileform, 'userform': userform})
return render(request, 'profiles/edit_profile.html', {'profileform': profileform, 'userform': userform})
Then, the userform which is causing the problem contains this odd-looking code:
class UserForm(forms.ModelForm):
class Meta:
model = User
exclude = ('last_login', 'date_joined', 'is_active', 'is_superuser', 'is_staff')
username = forms.CharField(widget=forms.TextInput(attrs={'readonly': 'readonly'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'readonly': 'readonly', 'value': '00000000000000000'}))
I'm not really sure what the value attr in password is meant to be doing. Anyway, I tried to modify this by adding the following to the UserForm:
def save(self, commit=True):
user = super(UserForm, self).save(commit=False)
password = self.cleaned_data["password"]
if len(password) > 0 and password != '00000000000000000':
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
I had no luck with this either, and if I simply omit the password field from the userform or the relevant html then the form does not validate.
<form method="post" action="" class="wide">
{% csrf_token %}
.....
<label for="id_password">Password:</label>
{{ userform.password }}
Can anyone suggest how this might be cleaned up?
Use a separate form for editing the password and remove it from this one. Add password
to the exclude
list and remove the field declaration.