I have the following signup flow in an app using Django 1.11-
accounts/views.py:
from .forms import UserForm
def sign_up(request):
if request.method == "POST":
form = UserForm(request.POST)
if form.is_valid():
user = form.save()
return redirect('index')
else:
form = UserForm()
return render(request, 'signup.html', {'form': form})
accounts/forms.py:
from django.forms import ModelForm
from django.contrib.auth.models import User
class UserForm(ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password']
It does appear to "register" a new user, in that it creates a new user in the database. The issue is I cannot login with that newly created user, the username/pw combo does not match. Going into the database I see the newly created users, but the password is in plain text: "password". But the first user I created through the command line, python manage.py createsuperuser
has a salted hash as the password like pasdfhjasf8234jk324hgsdfa8df89asdf987
and I can login correctly using the password I made for it, ie "password".
How do I save new users using my ModelForm where Django knows to correctly store the password as a salted hash?
You can not set the password through the boilerplate code in the ModelForm
, you need to use .set_password(..)
[Django-doc] to hash the password:
class UserForm(ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password']
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
Django however has already a UserCreationForm
[Django-doc] that implements this. It will use two form fields to validate that the user has entered the same password twice. We can thus subclass the UserCreationForm
:
from django.contrib.auth.forms import UserCreationForm
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email']