how to print forms.ValidationError in django - django

found this in a tutorial but "password and confirm_password does not match" is not printing to html page.
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput())
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=254)
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password','confirm_password']
def clean(self):
cleaned_data = super(UserForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)
UPDATE:
Worked using {{form.non_field_errors}} in the template.

Numerous way you can do it,from your views,forms also from your model
Class UserForm(forms.ModelForm):
pass
def clean_password(self):
data = self.cleaned_data
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError('Passwords must be same')
BTW
If using Python 3.6 then super().method_name(args),
if using 2.7 then super(class_name,self).method_name(args)

try:
def clean(self):
cleaned_data = super(UserForm, self).clean()
password = cleaned_data.get("password")
confirm_password = cleaned_data.get("confirm_password")
if password != confirm_password:
raise forms.ValidationError(
"password and confirm_password does not match"
)
else:
form = UserForm()
# If form is not valid, this would re-render
return render(request, 'template.html', {'form': form})

Related

How do I register a custom user type in Django 4.1?

So, I am a beginner and I'm coding a django application that has a 3 user types in total but to make the code readable and understandable I'm just gonna assume we have 2 user types. One is a doctor and one is a patient.
I've created this custom user so far:
in models.py
class User(AbstractUser):
is_doc = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
objects = UserManager()
manager.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if email is None:
raise TypeError('Users must have an email address.')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_patient(self, email, password):
if password is None:
raise TypeError('Must have a password')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.is_patient = True
user.save()
def create_superuser(self, email, password):
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
Patient Model is as follows:
class Patient(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
address = models.CharField(max_length=210)
phone = models.CharField(max_length=15)
email = models.EmailField(max_length=110)
password = models.CharField(max_length=65)
def __str__(self):
return self.first_name + " " + self.last_name
My form for Patient:
class PatientForm(forms.ModelForm):
class Meta:
model = Patient
fields = ['first_name', 'last_name', 'address', 'phone', 'email', 'password']
widgets = {
'first_name': forms.TextInput(attrs={'placeholder': 'First Name'}),
'last_name': forms.TextInput(attrs={'placeholder': 'Last Name'}),
'address': forms.TextInput(attrs={'placeholder': 'Address'}),
'phone': forms.TextInput(attrs={'placeholder': 'Phone Number'}),
'email': forms.EmailInput(attrs={'placeholder': 'Email'}),
'password': forms.PasswordInput(attrs={'placeholder': 'Password (Minimum Length: 8)'}),
}
Current Views.py:
def RegPatient(request):
if request.method == "POST":
form = PatientForm(request.POST)
if form.is_valid():
FName = form.cleaned_data['first_name']
LName = form.cleaned_data['last_name']
C_Address = form.cleaned_data['address']
C_Phone = form.cleaned_data['phone']
C_Email = form.cleaned_data['email']
C_Password = form.cleaned_data['password']
Reg = Patient(first_name= FName, last_name= LName, address= C_Address, phone= C_Phone, email= C_Email, password= C_Password)
Reg.save()
return HttpResponseRedirect('/Login/')
else:
for field in form.errors:
form[field].field.widget.attrs['class'] += ' is-invalid'
return render(request, 'Home/RegPatient.html', {'form': form})
else:
form = PatientForm()
return render(request, 'Home/RegPatient.html', {'form': form})
I have separate signups for patient and doctor and don't want a user type field in my form so I have all the detail fields in my form except user type.
How should my view look like so that it saves Patient with a user type is_patient? and am I missing something out? Cause I've tried to edit it so many times, tried getting help from Django Docs but I'm still stuck.
First, lets talk about the Manager and Models. The Manager you are using is not really necessary, its possible to just set up the field on User object creation. As for the Model you can use model inheritance to have an extended Patient model based on your User model:
class User(AbstractUser):
is_doctor = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
class Patient(User):
address = models.CharField(max_length=210)
phone = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Patients"
Although, I would say the right approach to your problem is to use Django authentication groups, instead of adding fields to your User model.
As for the signup form, it should contain confirmation and validation of the password and the username field unless you are doing a login with email. To hold the information of is_patient field, use an HiddenInput (I couldn't replicate it with 'ModelForm' will need to dig further into that.):
forms.py
from django.contrib.auth.hashers import make_password
from django.forms import ValidationError
class PatientSignUpForm(forms.Form):
username = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'username'}))
first_name = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'first name'}))
last_name = forms.CharField(
required=False,
widget=forms.TextInput(attrs={'placeholder': 'last name'}))
email = forms.EmailField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'email'}))
address = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'address'}))
phone = forms.CharField(
required=True,
widget=forms.TextInput(attrs={'placeholder': 'XXX-XXXXXXXXX'}))
password = forms.CharField(required=True, widget=forms.PasswordInput)
password_confirmation = forms.CharField(required=True, widget=forms.PasswordInput)
is_patient = forms.BooleanField(widget=forms.HiddenInput)
def clean(self):
password = self.cleaned_data['password']
password_confirmation = self.cleaned_data['password_confirmation']
if len(password) < 8 or len(password_confirmation) < 8:
raise ValidationError("Passwords must have at least 8 characters")
elif password != password_confirmation:
raise ValidationError("Passwords must be equal")
else:
self.cleaned_data['password'] = make_password(self.cleaned_data['password_confirmation'])
del self.cleaned_data['password_confirmation']
return self.cleaned_data
Lastly, in views.py create an instance of PatientSignUpForm with an initial value for is_patient field.
from app import models, forms
def patient_signup(request):
if request.method == 'POST':
form = forms.PatientSignUpForm(request.POST)
if form.is_valid():
models.Patient.objects.create(**form.cleaned_data)
return redirect('')
else:
form = forms.PatientSignUpForm(initial={'is_patient': True})
return render(request, 'patient_signup.html', {'form': form})

RegisterForm() missing 1 required positional argument: 'request'

So I'm making a custom user model. This is what I'am following Here. I have been pretty much following the tutorial but still I cant make it done.
Error: RegisterForm() missing 1 required positional argument: 'request'.
here's my code.
forms.py
from django import forms
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import 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)
class Meta:
model = User
fields = ('email',)
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 = ('email', 'password', 'active', 'admin')
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"]
class LoginForm(forms.ModelForm):
email = forms.EmailField(label='Email')
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email', 'password',)
widgets = {
'email' : forms.EmailInput(
attrs={'class':'form-control', 'place_holder': '', }),
'password' : forms.PasswordInput(
attrs={'class':'form-control' }),
}
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email',)
def clean_email(self):
email = self.cleaned_data.get('email')
qs = User.objects.filter(email=email)
if qs.exists():
raise forms.ValidationError("email is taken")
return email
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
models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class UserManager(BaseUserManager):
def create_user(self, email, full_name, password=None, is_staff=False, is_active=True, is_admin=False):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('Users must have an email address')
if not full_name:
raise ValueError('Users must have an full name')
if not password:
raise ValueError('Users must have a password')
user = self.model(
email=self.normalize_email(email),
)
user.full_name = full_name
user.set_password(password)
user.staff = is_staff
user.admin = is_admin
user.active = is_active
user.save(using=self._db)
return user
def create_staffuser(self, email, password):
"""
Creates and saves a staff user with the given email and password.
"""
user = self.create_user(
email,
password=password,
)
user.staff = True
user.save(using=self._db)
return user
def create_superuser(self, email, full_name, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.model(
email=self.normalize_email(email)
)
user.full_name = full_name
user.set_password(password)
user.full_name = full_name
user.staff = True
user.admin = True
user.save(using=self._db)
return user
# Create your models here.
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
full_name = models.CharField(max_length=255, null=True, blank=True)
active = models.BooleanField(default=True) # to login
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser
created_date = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name'] # Email & Password are required by default.
objects = UserManager()
def __str__(self):
return self.email
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
return self.staff
#property
def is_admin(self):
"Is the user a admin member?"
return self.admin
#property
def is_active(self):
"Is the user active?"
return self.active
class Account_type(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
account_type = models.ForeignKey(Account_type, on_delete=models.CASCADE)
register.html
from django.shortcuts import render, redirect
from . forms import RegisterForm, LoginForm
# Create your views here.
def RegisterForm(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
else:
form = RegisterForm()
context = {
'form' : form
}
return render(request, 'account/register.html', context)
The view logic is simple as you can see. Just saving up the request into the database. The tutorial itself did not tell anything about the view for login and register.
So, What am I doing wrong here.
Thank you
The problem is that your view RegisterForm has the same name as your form, hence if you call RegisterForm in your view, it will resolve to the view function, and make a recursive call.
Normally (top-level) functions are written in snake_case, hence you can rewrite it to register_form, or even better register (since it is not a form at all):
from django.shortcuts import render, redirect
from . forms import RegisterForm, LoginForm
# Create your views here.
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect('some-view-name')
else:
form = RegisterForm()
context = {
'form' : form
}
return render(request, 'account/register.html', context)
Normally a successful POST request results in a redirect to implement the Post/Redirect/Get pattern [wiki]. So I strongly advise you to use redirect(..) [Django-doc] and replace some-view-name with the name of a view to which you want to redirect.

The key "(User_id) = (51)" already exists

ERROR: repetitive record violates the singular constraint "user_otherinfo_user_id_key"
DETAIL: The key "(user_id) = (52)" already exists.
models.py
class OtherInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
phone = models.CharField(max_length=11,verbose_name="phone number")
location = models.CharField(max_length=50,verbose_name="location")
profile_image = models.FileField(blank = True,null = True,verbose_name="image")
class Meta:
verbose_name_plural = 'Other informations'
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
OtherInfo.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.otherinfo.save()
forms.py
class LoginForm(forms.Form):
username = forms.CharField(label = "Username")
password = forms.CharField(label = "Parola",widget = forms.PasswordInput)
class RegisterForm(forms.ModelForm):
password1 = forms.CharField(max_length=100, label='Parola',widget=forms.PasswordInput())
password2 = forms.CharField(max_length=100, label='Parola again', widget=forms.PasswordInput())
phone_number = forms.CharField(required=False, max_length=11, label='Phone Number')
location = forms.CharField(required=False, max_length=50, label='Location')
profile_image = forms.FileField(required=False, label="Image")
class Meta:
model = User
fields = [
'first_name',
'last_name',
'email',
'username',
'password1',
'password2',
'phone_number',
'location',
'profile_image',
]
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 do not match!")
return password2
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileForm(forms.ModelForm):
class Meta:
model = OtherInfo
fields = ('phone', 'location', 'profile_image')
views.py
#login_required
#transaction.atomic
def updateprofile(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
profile_form = ProfileForm(request.POST, instance=request.user.otherinfo)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, _('Your profile has been successfully updated!'))
return redirect('/user/profile/')
else:
messages.error(request, _('Please correct the following error.'))
else:
user_form = UserForm(instance=request.user)
profile_form = ProfileForm(instance=request.user.otherinfo)
return render(request, 'user/update_user.html', {
'user_form': user_form,
'profile_form': profile_form
})
def register(request):
form = RegisterForm(request.POST or None,request.FILES or None )
if form.is_valid():
user = form.save(commit=False)
first_name = form.cleaned_data.get('first_name')
last_name = form.cleaned_data.get('last_name')
username = form.cleaned_data.get("username")
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password1')
phone = form.cleaned_data.get('phone_number')
location = form.cleaned_data.get('location')
profile_image = form.cleaned_data.get('profile_image')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username, first_name=first_name, last_name=last_name, email=email, password=password)
OtherInfo.objects.create(user=new_user,phone=phone,location=location,
profile_image=profile_image)
login(request,new_user)
messages.info(request,"Successfully Register ...")
return redirect("/")
context = {
"form" : form
}
return render(request,"user/register.html",context)
In Django, the user can register before updating the profile. When I add the profile update code, now the user is failing to register. How can I solve the problem?
It's simply a matter of not creating twice a OtherInfo for the same User:
in the post_save handler of saving a User, you create a OtherInfo object for the user.
in your view, you first create the User, hence you already create the OtherInfo associated with the user.
then you have OtherInfo.objects.create(user=new_user,phone=phone,location=location,
profile_image=profile_image)
This last instruction will fail, because you're trying to create a second OtherInfo for the same user. So you can do two things:
Remove the post_save signal handler that creates the OtherInfo object
or
Update new_user.otherinfo by setting the various values and saving it instead of creating it.
You need to delete the data entry with id=51.
The error you get is related to database, that the entry with id you are trying to create already exists.
Drop your database and create a new one(If you are not on a production environment)

self.cleaned_data.get returns none even if field was declared

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

Django user registration validation not working

Hello i want to develop validation to user registration if user exists and is password matches the password confirmation field. Unfortunately, validation doesn't works. For example, if the 2 passwords don't match, the registration completes anyway with the first password. I want, if there is a problem to reload the registration form with the problems highlighted.
the form:
class RegistrationForm(forms.Form):
username = forms.CharField(label=u'Username', max_length=30)
first_name = forms.CharField(label=u'First Name', max_length=30)
last_name = forms.CharField(label=u'Last Name', max_length=30)
email = forms.EmailField(label=u'Email')
password1 = forms.CharField(
label=u'Password',
widget=forms.PasswordInput()
)
password2 = forms.CharField(
label=u'Password (Again)',
widget=forms.PasswordInput()
)
def clean_password2(self):
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w+$', username):
raise forms.ValidationError('Username can only contain '
'alphanumeric characters and the underscore.')
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
the view:
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
UserProfile.first_name=form.cleaned_data['first_name']
created = UserProfile.objects.get_or_create(
user_id=user.id, first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name'] )
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {
'form': form
})
return render_to_response(
'registration/register.html', variables)
class RegistrationForm(forms.Form):
//fields
def clean(self):
cleaned_data = super(RegistrationForm, self).clean()
username = cleaned_data.get("username")
password1 = cleaned_data.get("password1")
password1 = cleaned_data.get("password1")
#validate username
user = User.objects.filter(username=username)
if user:
raise forms.ValidationError(
"That user is already taken , please select another ")
elif not re.search(r'^\w+$', username):
raise forms.ValidationError(
"Username can only contain"
"alphanumeric characters and the underscore.")
#validate password
if password1 != password1:
raise forms.ValidationError(
"Your current and confirm password do not match.")
return cleaned_data
I use this simple validation which works.
def validate(self, value):
data = self.get_initial()
username = data.get("username")
email = data.get("email")
password = data.get("password")
confirm_password = data.get("confirm_password")
max_similarity = 0.7
user_qs = User.objects.filter(email=username)
if user_qs.exists():
raise ValidationError("Username already exist")
if(password != confirm_password):
raise ValidationError("Password and Confirm password does not match")
if SequenceMatcher(a=password.lower(), b=username.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the username.")
if SequenceMatcher(a=password.lower(), b=email.lower()).quick_ratio() > max_similarity:
raise serializers.ValidationError("The password is too similar to the email.")
return data
Additional validation:
Also you can add some default validation of django by adding this.
This will check minimum length of the password and max string and max integer.
def validate_password(self, value):
try:
validate_password(value)
except ValidationError as exc:
raise serializers.ValidationError(str(exc))
return value