I want to have a user sign up form in Django, I know that for the Backend I should have something like this:
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon#thebeatles.com', 'johnpassword')
>>> user.last_name = 'Lennon'
>>> user.save()
However, I don't know how to make the Frontend. I've already looked up in the Django documentation and found the UserCreationForm class and it says it's deprecated.
What should I do? Thank you
Try something like this:
#forms.py
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
You should read this section of the Django Docs on authentication.
Related
Stumbled this def clean_password2 ModelForm.
My question is does every time this we run this view. Does it will automatically run clean_password2 to check the password or do we need to explicitly call it?
Form.py
class RegisterForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('full_name', 'email',) #'full_name',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.is_active = False # send confirmation email via signals
# obj = EmailActivation.objects.create(user=user)
# obj.send_activation_email()
if commit:
user.save()
return user
https://docs.djangoproject.com/en/4.0/topics/auth/customizing/#a-full-example
No, you don't have to call it explicitly as it says in the doc.
The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute. This method does any cleaning that is specific to that particular attribute, unrelated to the type of field that it is. This method is not passed any parameters. You will need to look up the value of the field in self.cleaned_data and remember that it will be a Python object at this point, not the original string submitted in the form (it will be in cleaned_data because the general field clean() method, above, has already cleaned the data once).
doc: https://docs.djangoproject.com/en/4.0/ref/forms/validation/
I am making a registration form for 3 types of users. When a user enters email and password he/she must select one of the roles.
First I used BooleanFields and it works, but more than one checkbox can be selected. I need that user can select only one role.
I have tried ChoiceField, which I could display on the template but it does not POST any data to db.
forms.py
class RegisterForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
parent = forms.BooleanField(label="I am a Parent")
school = forms.BooleanField(label="I am a School Admin")
vendor = forms.BooleanField(label="I am a Vendor")
role_select=forms.ChoiceField(
widget=forms.RadioSelect,
label="Select your role.",
choices=(('is_parent','parent '),('is_school','school'),('is_vendor','vendor')),
)
if not parent and not school and not vendor:
raise forms.ValidationError("Users must have a role")
class Meta:
model = User
fields = ['role_select', 'parent', 'school', 'vendor', 'email'] #'full_name',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
user.role_select( self.cleaned_data['role_select'])
# user.active = False # send confirmation email
if commit:
user.save()
return user
As you see in the forms.py I have a combination of two approaches. So it has some useless lines. Which approach to use and how?
you can use Django groups where you can create a group and assign it as a choicefield when user registers. You can check my repository. I have done the same thing here. Hope it can get you some idea
https://github.com/tsephel/User-authentication-django-/tree/master/env
I created a customized User Admin change form but when I create a new user it goes to the Change form.
The Base Admin add form meets what I want hence why I want to keep it?
Also how do I encrypt the password once I reverted back to the Base admin create form?
How do I change this?
Admin.py:
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminChangeForm
from .models import User
# Register your models here.
User=get_user_model()
class UserAdmin(admin.ModelAdmin):
form = UserAdminChangeForm
search_fields=['username','user_type']
list_display=('username','full_name','password','email','user_type','ad','pqa','ts','tl','tm','stm','active')
list_filter = ('ad',)
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal info', {'fields': ('full_name','birth_date','hire_date',)}),
('Permissions', {'fields': ('ad','tm','pqa','stm','ts','tl')}),
)
class Meta:
model = User
admin.site.register(User,UserAdmin)
forms.py:
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import User
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
usertype= forms.Select(choices=User.USER_TYPE_CHOICES)
class Meta:
model = User
fields = ('username',)
def clean_username(self):
username = self.cleaned_data.get('username')
qs = User.objects.filter(username=username)
if qs.exists():
raise forms.ValidationError("Username is taken")
return username
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit = True):
user = super(RegisterForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminCreationForm(forms.ModelForm):
"""
A form for creating new users. Includes all the required
fields, plus a repeated password.
"""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
usertype= forms.Select(choices=User.USER_TYPE_CHOICES)
class Meta:
model = User
fields = ['username','password','user_type']
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserAdminCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserAdminChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
fields = ('username', 'password', 'active', 'ad')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
I really appreciate the help. TIA
so i have been follow Django Documentation example regarding Custom user Model (AbstractBaseUser). But when i create user from admin site it started giving me this error
"local variable 'password1' referenced before assignment"
Below i Have include admin.py
from django.contrib import admin
from django import forms
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
class UserCreationForm(forms.ModelForm):
password1 = forms.CharField(label= 'Password' , widget =
forms.PasswordInput)
password2 = forms.CharField(label = 'Password Confirmation', widget =
forms.PasswordInput)
class Meta:
model = CustomUser
#with my added feilds in AbstractBaseUser
fields = ('email','first_name','last_name', 'Mobile',
'Aadhar_Card', 'Address','is_supervisor','is_employee','is_driver')
def clean_password2(self):
password1 = self.cleaned_data.get(password1)
password2 = self.cleaned_data.get(password2)
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords Dont Match")
return password2
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
Your clean_password2 method is indeed referencing undefined variables. You need to use strings:
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
When i'm in the admin page and trying to create a new instance of MyUser I am unable to create it. When I print out password and confirm_password, I get the proper value for password but None for confirm_password.
In my admins.py file, I have the following:
class MyUserCreationForm(forms.ModelForm):
"""
A form for creating new users.
"""
password = forms.CharField(label='Password', widget=forms.PasswordInput)
confirm_password = forms.CharField(
label='Confirm password', widget=forms.PasswordInput)
class Meta:
models = MyUser
fields = ('email', )
def clean_password(self):
"""
Check if two password entries match.
"""
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if (password == confirm_password):
return password
else:
raise forms.ValidationError("Passwords don't match")
def save(self):
"""
Save the provided password in hash format.
"""
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
user.save()
return user
What could be causing as to why confirm_password always have the value None?
You should not do this code in the clean_password.
It makes more sense to do it inside clean_confirm_password
Here is a snipet retrieve from django source code:
def clean_confirm_password(self):
password = self.cleaned_data.get("password")
confirm_password = self.cleaned_data.get("confirm_password")
if password and confirm_password and password != confirm_password:
#you can keep your simply Validation Error here
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
And for the save try:
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
Otherwise your code seems to be good.
So maybe the error is somewhere else.
Here for your information: https://github.com/django/django/blob/master/django/contrib/auth/forms.py#L70