Email Verification Check - python

I want to have an email check in my email form field so that if the user's email doesn't end with '#aun.edu.ng' it will through an error message.
forms.py
class EmployeeRegistrationForm(forms.ModelForm):
first_name = forms.CharField(label='First Name')
last_name = forms.CharField(label='Last Name')
cv = forms.FileField(label='CV')
skills_or_trainings = forms.SlugField(label='Skills or Trainings', required=False, widget=forms.Textarea)
class Meta:
model = Student
fields = ['first_name', 'last_name', 'gender', 'level', 'school', 'major', 'cv', 'skills_or_trainings' ]
class EmployerRegistrationForm(forms.ModelForm):
company_name = forms.CharField(label="Company Name")
company_address = forms.CharField(label="Company Address")
website = forms.CharField()
class Meta:
model = Employer
fields = ['company_name', 'company_address', 'website']
views.py
def student_register(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
student_form = EmployeeRegistrationForm(request.POST)
if form.is_valid() and student_form.is_valid():
user = form.save(commit=False)
user.is_student = True
user.save()
student = student_form.save(commit=False)
student.user = user
student.save()
return redirect('login')
else:
form = UserRegistrationForm()
student_form = EmployeeRegistrationForm()
context = {'form': form, 'student_form': student_form}
return render (request, 'accounts/employee/register.html', context)
def employer_register(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
employer_form = EmployerRegistrationForm(request.POST)
if form.is_valid() and employer_form.is_valid():
user = form.save(commit=False)
user.is_employer = True
user.save()
employer = employer_form.save(commit=False)
employer.user = user
employer.save()
return redirect('login')
else:
form = UserRegistrationForm()
employer_form = EmployerRegistrationForm()
context = {'form': form, 'employer_form': employer_form}
return render (request, 'accounts/employer/register.html', context)
Please how do I go about it so that I will be able to through a Validation Error message when the user puts in an email that doesn't end with '#aun.edu.ng'
Thank you

To raise validation error for the employer you can do this by overriding the clean() method of the EmployerRegistrationForm form.
from django.form import ValidationError
class EmployerRegistrationForm(forms.ModelForm):
company_name = forms.CharField(label="Company Name")
company_address = forms.CharField(label="Company Address")
website = forms.CharField()
class Meta:
model = Employer
fields = ['company_name', 'company_address', 'website']
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('company_address').endswith('#aun.edu.ng'):
raise ValidationError('This email is not applicable')
return cleaned_data

See this answer for a regular expression that matches email addresses. You can use this in Python with the regular expression module. If the email is invalid, just send them back to the login with a message saying the email address is invalid.
import re
email_re = """(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"""
if re.match(email_re, "someone#example.com"):
print("Match found")
else:
print("Invalid email address")
Please note that valid email addresses include unregistered email addresses and the only way to verify an email address completely is to send them an email with a verification link. This link would then allow them to "unlock" the account created.

Related

Why I get "KeyError" exception in django instead of "This field is required" exception on the form validation

I'm new to Django, I have a registration form, Everything works fine If I fill all fields and when I don't fill all the fields. But when I submit a form without a username field I get a "Key Error" instead of "This field is required" Exception since I have declared the field is required on the form class.
forms.py
class UserRegistration(forms.ModelForm):
first_name = forms.CharField(label='First Name', max_length=50)
last_name = forms.CharField(label='Last Name', max_length=50)
username = forms.CharField(label='Username', max_length=50)
email = forms.EmailField(label='Email', max_length=50)
password = forms.CharField(label='Password', widget=forms.PasswordInput, max_length=50, validators = [validators.MinLengthValidator(6)])
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput, max_length=50)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password', 'password2')
def clean_username(self):
username = self.cleaned_data['username']
email = self.cleaned_data['email']
if username and User.objects.filter(username=username).exclude(email=email).count():
raise forms.ValidationError('This username address is already in use.')
return username
def clean_email(self):
email = self.cleaned_data['email']
username = self.cleaned_data['username']
if email and User.objects.filter(email=email).exclude(username=username).count():
raise forms.ValidationError('This email address is already in use.')
return email
def clean_password(self):
password = self.cleaned_data['password']
if len(password) < 6:
raise forms.ValidationError("Password is too short")
return password
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
views.py
def register(request):
if request.method == 'POST':
form = UserRegistration(request.POST)
if form.is_valid():
new_user = form.save(commit=False)
new_user.set_password(
form.cleaned_data.get('password')
)
new_user.save()
return render(request, 'authapp/register_done.html')
else:
return render(request, 'authapp/register.html', {'form':form})
else:
form = UserRegistration()
context = {
"form": form
}
return render(request, 'authapp/register.html', context=context)
Error Traceback
Error Page Screenshot
Request Information Post data
When creating Form, update the username field with required and Null
Yes, by default required will be True but it is a constraint for the DB side while the 'null' field is used when any widget is must from UI side
username = forms.CharField(label='Username', max_length=50,required=True,null=False)
And about error you got : username validator is saving empty name so empty data is accessed and used in email validation
After googling and researching "KeyError" Exception, I have found that the error is caused by accessing a dictionary value with a key 'username' that doesn't exist, hence the KeyError. So it's more of a programming error than Django itself. The solution is to check for the key if it exists before accessing it or use
username = self.cleaned_data.get('username')
instead of
username = self.cleaned_data['username']
according to https://www.journaldev.com/33497/python-keyerror-exception-handling-examples#:~:text=We%20can%20avoid%20KeyError%20by,when%20the%20key%20is%20missing.

User model is not saving create_user instances

I have made a form having fields of personal information and login information as one
models.py
class EmployeeModel(models.Model)
employee_id = models.CharField(max_length=300,unique=True,help_text='Employee ID should not be same')
name = models.CharField(max_length=300)
username = models.CharField(max_length=50,null=True,blank=True)
email = models.EmailField(null=True,blank=True)
password = models.CharField(max_length=20,null=True,blank=True)
password_confirm = models.CharField(max_length=20,null=True,blank=True)
forms.py
class EmployeeForm(forms.ModelForm):
class Meta:
model = employeeModel
fields = ('__all__')
views.py
User = get_user_model()
def create_view(request):
if request.method == 'POST':
form = employeeForm(request.POST or None,request.FILES or None)
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
User= get_user_model()
user= User.objects.create_user(username=username,email=email,password=password)
authenticate(request,username=username,email=email,password=password)
form.save()
return redirect('emp_list')
else:
form = employeeForm()
return render(request,'create_employee.html',{'form':form})
Its not showing any error but User.objects.all() shows only superuser not the users i created though this form. Those users i have created in this form are are showing up in Employee.objects.get(username='foo')
So what to do? I cant login through those non_superusers. it throws invalid login error. How to fix this?

Editing profile in django python

I am adding in some functionality that allows a user to edit their personal profile page information. When the user updates their info and hit submit they are getting a NameErrorsaying that the user is not defined. Below is how I am trying to implement the editing functionality.
forms
#this is all the information that the user is allowed to edit.
class UpdateProfile(forms.ModelForm):
username = forms.CharField(required=False)
email = forms.EmailField(required=False)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
age = forms.IntegerField(required=False)
height = forms.IntegerField(required=False)
weight = forms.IntegerField(required=False)
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'age', 'height', 'weight')
def clean_email(self):
username = self.cleaned_data.get('username')
email = self.cleaned_data.get('email')
if email and User.objects.filter(email=email).exclude(username=username).count():
raise forms.ValidationError('This email address is already in use. Please supply a different email address.')
return email
def save(self, commit=True):
# user = super(RegisterUserForm, self).save(commit=False)
user.email = self.cleaned_data['email']
#This is where i am trying to save the new information.
if commit:
user.save()
#This is where i am returning the user.
return user
Views
def update_profile(request):
args = {}
if request.method == 'POST':
form = UpdateProfile(request.POST, instance=request.user)
form.actual_user = request.user
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('account:profile.html'))
else:
form = UpdateProfile()
args['form'] = form
return render(request, 'account/edit_profile.html', args)

How to make Required: boolean field in model Django

I have a model with a field called in is_student and is_teacher Student and Teacher forms
is_teacher = models.BooleanField('teacher status', default=False)
is_student = models.BooleanField('student status', default=False)
I want to make sure this field is:
Always Checked by the user True *Required
Currently: is_teacher in TeacherApplications Model
When unchecked - it saved 0 to the form and continues. (Not good)
When checked gives me this error:
ValueError at /register/teacher invalid literal for int() with base
10: ''
Currently: is_student in StudentProfile Model
When checked gives this error
ValidationError at /register/ ["'on' value must be either True or
False."]
When unchecked it saved 0 to the form and continues. (Again, not good)
UPDATED CODE
Above errors are gone: New error each time I try to submit form after checking is_teacher/is_student
IntegrityError at /register/ NOT NULL constraint failed:
accounts_studentprofile.is_student
model
class StudentProfile(models.Model):
user = models.OneToOneField('Accounts', related_name='student_profile')
# additional fields for students
AMEB_Ratings = models.PositiveIntegerField(default=0)
is_student = models.BooleanField('student status', default=False)
class TeacherApplications(models.Model):
user = models.OneToOneField('Accounts', related_name='teacher_profile')
# additional fields for teachers
instrument = models.TextField(max_length=500, blank=True)
skill = models.CharField(max_length=30, blank=True)
experience_in_years = models.PositiveIntegerField(blank=True)
is_teacher = models.BooleanField('teacher status', default=False)
view
def registerStudent(request):
# Once register page loads, either it will send to the server POST data (if the form is submitted), else if it don't send post data create a user form to register
if request.method == "POST":
user_form = UserForm(request.POST)
form = StudentResistrationForm(request.POST)
if form.is_valid() and user_form.is_valid():
User = get_user_model()
username = user_form.cleaned_data['username']
email = user_form.cleaned_data['email']
password = user_form.cleaned_data['password']
new_user = User.objects.create_user(username=username, email=email, password=password)
student = form.save(commit=False)
student.user = new_user
student.save()
# Student_profile = StudentProfile()
# Student_profile.user = new_user
# Student_profile.AMEB_Ratings = request.POST['AMEB_Ratings']
# Student_profile.is_student = request.POST.get('is_student', False)
new_user.save()
# Student_profile.save()
# form.save()
return redirect('/')
else:
# Create the django default user form and send it as a dictionary in args to the reg_form.html page.
user_form = UserForm()
form = StudentResistrationForm()
# args = {'form_student': form, 'user_form': user_form }
return render(request, 'accounts/reg_form_students.html', {'form_student': form, 'user_form': user_form })
def teacherApplication(request):
# Once register page loads, either it will send to the server POST data (if the form is submitted), else if it don't send post data create a user form to register
if request.method == "POST":
user_form = UserForm(request.POST)
form = TeacherRegistrationForm(request.POST)
if form.is_valid() and user_form.is_valid():
User = get_user_model()
username = user_form.cleaned_data['username']
email = user_form.cleaned_data['email']
password = user_form.cleaned_data['password']
new_user = User.objects.create_user(username=username, email=email, password=password)
teacher = form.save(commit=False)
teacher.user = new_user
teacher.save()
# Teacher_profile = TeacherApplications()
# Teacher_profile.user = new_user
# Teacher_profile.instrument = request.POST['instrument']
# Teacher_profile.skill = request.POST['skill']
# Teacher_profile.experience_in_years = request.POST['experience_in_years']
# Teacher_profile.is_teacher = request.POST.get('is_teacher', False)
new_user.save()
# Teacher_profile.save()
# form.save()
return redirect('/')
else:
# Create the django default user form and send it as a dictionary in args to the reg_form.html page.
user_form = UserForm()
form = TeacherRegistrationForm()
return render(request, 'accounts/reg_form_teachers.html', {'form_student': form, 'user_form': user_form })
forms
class StudentResistrationForm(forms.ModelForm):
class Meta:
model = StudentProfile
fields = (
'AMEB_Ratings',
'is_student',
)
def save(self, commit=True):
user = super(StudentResistrationForm, self).save(commit=False)
# user.first_name = self.cleaned_data['first_name']
# user.last_name = self.cleaned_data['last_name']
user.AMEB_Ratings = self.cleaned_data['AMEB_Ratings']
if commit:
user.save()
return user
class TeacherRegistrationForm(forms.ModelForm):
class Meta:
model = TeacherApplications
fields = (
'instrument',
'skill',
'experience_in_years',
'is_teacher',
)
class UserForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ('username', 'email', 'password')
You can add this fields to StudentResistrationForm and TeacherRegistrationForm and add custom validation for it in clean_fieldname method to make it required:
StudentResistrationForm(ModelForm):
class Meta:
model = StudentRegistration
fields = (
'instrument',
'skill',
'experience_in_years',
'is_student',
)
def clean_is_student(self):
is_student = self.cleaned_data.get('is_student')
if not is_student:
raise forms.ValidationError('This field is required')
return is_student
Also in view instead of getting raw data from request.POST you can use forms to create student and teacher objects:
new_user = User.objects.create_user(username=username, email=email, password=password)
teacher = form.save(commit=False)
teacher.user = new_user
teacher.save()

Django - how to save my hashed password

I'm trying to save my hashed password in my database, but It keeps saving my plaintext password
Models:
class StudentRegistration(models.Model):
email = models.EmailField(max_length=50)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
password = models.CharField(max_length=100, default="", null=False)
prom_code = models.CharField(max_length=8, default="", null=False)
gender = (
("M","Male"),
("F","Female"),
)
gender = models.CharField(max_length=1, choices=gender, default="M", null=False)
prom_name = models.CharField(max_length=20, default="N/A")
prom_year = models.IntegerField(max_length=4, default=1900)
school = models.CharField(max_length=50, default="N/A")
def save(self):
try:
Myobj = Space.objects.get(prom_code = self.prom_code)
self.prom_name = Myobj.prom_name
self.prom_year = Myobj.prom_year
self.school = Myobj.school_name
super(StudentRegistration, self).save()
except Space.DoesNotExist:
print("Error")
Views:
def register_user(request):
args = {}
if request.method == 'POST':
form = MyRegistrationForm(request.POST) # create form object
if form.is_valid():
clearPassNoHash = form.cleaned_data['password']
form.password = make_password(clearPassNoHash, None, 'md5')
form.save()
form = MyRegistrationForm()
print ('se salvo')
else:
print ('Error en el form')
else:
form = MyRegistrationForm()
args['form'] = form #MyRegistrationForm()
return render(request, 'register/register.html', args)
I've printed the hashed result so I know it is hashing but not saving that.
Am I using the make_password wrong? or is there any better way to protect my passwords?
--------------------------UPDATE:(The Solution)----------------------------
Remember In settings.py:
#The Hasher you are using
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.MD5PasswordHasher',
)
Models.py:
#Import and add the AbstractBaseUser in your model
class StudentRegistration(AbstractBaseUser, models.Model):
Views.py:
if form.is_valid():
user = form.save(commit=False)
clearPassNoHash = form.cleaned_data['password']
varhash = make_password(clearPassNoHash, None, 'md5')
user.set_password(varhash)
user.save()
Use Django set_password in the documentation
https://docs.djangoproject.com/en/1.9/ref/contrib/auth/
You also need to get your model object from the form using form.save(commit=False)
if form.is_valid():
# get model object data from form here
user = form.save(commit=False)
# Cleaned(normalized) data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
# Use set_password here
user.set_password(password)
user.save()
Save the object first, without committing to DB, then update password before a final save. Make sure your imports are all correct.
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST) # create form object
if form.is_valid():
new_object = form.save(commit=False)
new_object.password = make_password(form.cleaned_data['password'])
new_object.save()
messages.success(request, "Form saved.")
return redirect("somewhere")
else:
messages.error(request, "There was a problem with the form.")
else:
form = MyRegistrationForm()
return render(request, 'register/register.html', { 'form': form })

Categories