Custom django user registration - django

I am doing a user registration function, this is views
from django.http import HttpResponseGone
from .forms import RegisterForms
from django.shortcuts import render
def register(request):
if request.method == 'POST':
user_forms = RegisterForms(request.POST)
if user_forms.is_valid():
new_userform = user_forms.save(commit=False)
new_userform.set_password(user_forms.cleaned_data['password'])
new_userform.save()
return HttpResponseGone('注册成功')
else:
return HttpResponseGone('注册失败')
else:
user_forms = RegisterForms()
return render(request,'account/register.html',{'form':user_forms})
this is forms
from django import forms
from django.contrib.auth.models import User
class RegisterForms(forms.ModelForm):
password = forms.CharField(label='Password',widget=forms.PasswordInput)
password2 = forms.CharField(label='password again',widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username','email')
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('密码输入不一致,请从新输入')
else:
return cd['password']
this is html
<p>欢迎注册</p>
<form action="." method="post">
{% csrf_token %}
<p>username {{ form.username }}</p>
<p>email {{ form.email }}</p>
<p>password {{ form.password }}</p>
<p>password again {{ form.password2 }}</p>
<input type="submit" value="register">
</form>
I found that if I change the name of the clean_password2 method in the views file to clean_password, I can not get the value of password2 in the form
This is the wrong message[enter image description here][4]
My English is not very good I hope someone can help me Thank Thank Thank

from django import forms
from django.contrib.auth.models import User
class RegisterForms(forms.ModelForm):
password = forms.CharField(label='Password',widget=forms.PasswordInput)
password2 = forms.CharField(label='password again',widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username','email','password','password2')
def clean(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('密码输入不一致,请从新输入')
else:
return cd
In short use clean method in such conditions.

Related

How to customize the validation error message in Django?

I am trying to create a registration page in Django and to check fields validation. I wanna set a custom validation error message to the email field. Can you help me, please?
Here is the view.py:
from django.shortcuts import render
from django.http import HttpResponse, request
from django.db import connection
from django.contrib.auth.decorators import login_required
import pyodbc
def newUser(request):
form = NewUserFrom(request.POST or None)
if not form.is_valid():
context = {'frmNewUser':form}
return render(request,'login/newuser.html', context)
return render(request, "login/welcome.html")
Here is the forms.py:
from ctypes import alignment
from email import message
from urllib import request
from django import forms
class NewUserFrom(forms.Form):
error_css_class = 'error'
username = forms.CharField(max_length=50, widget=forms.TextInput, label="Username")
password = forms.CharField(widget=forms.PasswordInput, label="Password")
confirm_password = forms.CharField(label="Confirm password", widget=forms.PasswordInput)
name = forms.CharField(max_length=50, widget=forms.TextInput, label="Name")
email = forms.EmailField(max_length=50, widget=forms.EmailInput, label="Email")
def clean_password(self):
cleaned_data = super().clean()
pwd = cleaned_data.get('password')
cof_pwd = cleaned_data.get('confirm_password')
# if pwd and cof_pwd:
if pwd != cof_pwd:
raise forms.ValidationError('Password is not match.')
return cleaned_data
def clean(self):
cleaned_data = super(NewUserFrom,self).clean()
email = cleaned_data.get('email')
if email.strip() == "".strip():
# self.add_error('email','Email is reqiered.')
raise forms.ValidationError('Email is reqiered.')
else:
fistPart, secPart = str(email).split('#')
raise forms.ValidationError('Email error.')
Here is the NewUser.html:
{% block content %}
<form method="POST">
{% csrf_token %}
<table>
{{frmNewUser.as_table}}
{% for field in frmNewUser.fields %}
{% if field.errors %}
{% for error in field.errors %}
<p style="color: red;">{{error}}</p>
{% endfor %}
{% endif %}
{% endfor %}
</table>
<input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}
You havn't mentioned against what conditions you want to validate the email. Most of the checks for a normal email shall be done by django in-build validators since you are using forms.EmailField. But if you want to do further checks, then you can create another clean method specially for the email field. Just an example to get you started.
def clean_email(self):
email = self.cleaned_data.get('email')
domain = email.split('#')[1]
if (domain == 'gmail') or (domain == 'yahoo'):
raise forms.ValidationError('Please use your official email id.')
return email

How to show the validation error in a Django form?

I am new to Django. I am trying to make a simple form to match the password. However, when I enter different passwords and press the Save button I get a cleared form instead of showing the validation error.
Here newuser.html:
{% block content %}
<form method="POST">
{% csrf_token %}
<table>
{{frmNewUser.as_table}}
{% for error in frmNewUser.password.errors %} {% comment %} I tried frmNewUser.non_field_errors too {% endcomment %}
<p>{{error}}</p>
{% endfor %}
</table>
<input type="submit" name="Save" value="Save" colspan=2>
</form>
{% endblock content %}
Here forms.py:
class NewUserFrom(forms.Form):
username = forms.CharField(max_length=50, widget=forms.TextInput)
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(label="Confirm password", widget=forms.PasswordInput)
name = forms.CharField(max_length=50, widget=forms.TextInput)
email = forms.EmailField(max_length=50, widget=forms.EmailInput)
def clean(self):
cleaned_data = super().clean()
pwd = cleaned_data.get('password')
cof_pwd = cleaned_data.get('confirm_password')
if pwd and cof_pwd:
if pwd != cof_pwd:
raise forms.ValidationError('Password is not match.')
return super().clean()
Here views.py:
from django.shortcuts import render
from django.http import HttpResponse, request
from django.db import connection
from django.contrib.auth.decorators import login_required
import pyodbc
from .forms import NewUserFrom
def newUser(request):
form = NewUserFrom(request.POST)
if not form.is_valid():
return render(request,'login/newuser.html', {'frmNewUser':NewUserFrom})
return render(request, "login/welcome.html")
Try following this article, it helped when i had a similar problem
in the newUser function
def newUser(request):
form = NewUserFrom(request.POST)
if not form.is_valid():
return render(request,'login/newuser.html', {'frmNewUser':NewUserFrom})
return render(request, "login/welcome.html")
the return value in the if statement should be changed from {'frmNewUser':NewUserFrom}) to {'frmNewUser':form})

Profile is not getting created for the new user after extension of the user model

Before extending the user module, I was easily able to register new users and the page would get redirected to the login page. Now on registering new users, the profile is not getting created and the page is also not getting redirected. The new user does get created though and sometimes the error is object does not exist, user profile does not exist, and sometimes the error is forbidden, csrf verification failed. I dont know where I'm going wrong. existing users are able to login and update profiles but new users I'm having a problem with.
Models.py is:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,null= True ,on_delete= models.CASCADE)
profile_pic = models.ImageField(null = True, blank= True)
first = models.CharField(max_length=500, null=True)
last = models.CharField(max_length=500, null=True)
email = models.CharField(max_length=500, null=True)
mobile_number = models.IntegerField(null=True)
location = models.CharField(max_length= 500, null= True)
postal = models.IntegerField(null=True)
def __str__(self):
return self.first
My forms.py is:
from django.forms import ModelForm, fields
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from .models import *
class CreateUserForm(UserCreationForm):
email = forms.EmailField()
password2 = None
class Meta:
model = User
fields = ['username','first_name', 'last_name','email', 'password1']
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
exclude = ['user']
widgets = {
'profile_pic': forms.FileInput()
}
views.py is (I removed the login and logout view cause that was working fine):
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from .forms import CreateUserForm, ProfileForm
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from .models import *
def RegisterPage(request):
if request.user.is_authenticated:
return redirect('Profile')
else:
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
user = form.save()
name = form.cleaned_data.get('first_name')
messages.success(request, 'Account created for ' + name)
Profile.object.create(
user = user,
)
Profile.save()
return HttpResponseRedirect('/Login/')
else:
form = CreateUserForm()
context = {'form':form}
return render(request, 'register.html', context)
#login_required(login_url='Login')
def Profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'profile.html', context)
my register template:
<form class="" action="" method="post">
{% csrf_token %}
<p class="reg-field-title"><strong>Username*</strong></p>
<div class="forms">{{form.username}}</div>
<p class="reg-field-title"><strong>First Name*</strong></p>
<div class="forms">{{form.first_name}}</div>
<p class="reg-field-title"><strong>Last Name*</strong></p>
<div class="forms">{{form.last_name}}</div>
<p class="reg-field-title"><strong>Email-ID*</strong></p>
<div class="forms">{{form.email}}</div>
<p class="reg-field-title"><strong>Password*</strong></p>
<div class="forms">{{form.password1}}</div>
<button type="submit" class="btn btn-dark btn-lg col-lg-10 reg-btn">Register</button>
</form>
My login template:
<p class="login-reg">New to MedsPlain? <a class="log-reg-link" href="/Registration/">Register </a>here</p>
<hr> {% if next %}
<form class="" action='/Login/Profile/' method="post"> {% csrf_token %} {%else%}
<form class="" action="/Login/" method="post">
{% endif %} {% csrf_token %}
<p class="login-field-title"><strong>Username*</strong></p>
<input type="text" name="username" class="form-control col-lg-10 log-inp-field" placeholder="Enter Username" required>
<p class="login-field-title"><strong>Password*</strong></p>
<input type="password" name="password" class="form-control col-lg-10 log-inp-field" placeholder="Enter Password" required> {% for message in messages %}
<p id="messages">{{message}}</p>
{% endfor %}
<button type="submit" class="btn btn-dark btn-lg col-lg-10 log-btn">Log In</button>
</form>
I've tried everything as of now, but i don't understand the mistake. Can someone please guide me through cause at this moment i'm frustrated, on the verge of crying and don't understand what to do.
There are basically two problems here:
there is a view Profile, and thus this will override the reference to the Profile model; and
you do not create a model record with Model.object.create(), but with Model.objects.create().
I would advise that you rename your views in snake_case, and remove the wildcard import, this is often not a good idea:
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from .forms import CreateUserForm, ProfileForm
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from .models import Profile
def register_page(request):
if request.user.is_authenticated:
return redirect('Profile')
else:
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
user = form.save()
Profile.objects.create(
user = user,
)
messages.success(request, 'Account created for {user.first_name}')
return HttpResponseRedirect('/Login/')
else:
form = CreateUserForm()
context = {'form': form }
return render(request, 'register.html', context)
#login_required(login_url='Login')
def profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'profile.html', context)
You will also need to update the urls.py to work with the renamed views.

Double users created

I have an issue with my code in the sense that when a student registers, a double instance of the student is created. I don't know what's the problem with these block of code. Please help out,also I don't know how to make a link between a teacher and a student so as to allow the teacher to add results for students.
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm,UserUpdateForm ,InformationUpdateForm,InformationForm
def home(request):
return render(request, 'student/home.html')
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
a_form=InformationForm(request.POST)
# ####and a_form.is_valid()
if form.is_valid() and a_form.is_valid():
user = form.save()
# form.save()
#finally this get links the models, forms and views for user input and all information is registered
information = a_form.save()
# a_form.save()
user.information.majors=a_form.cleaned_data.get('majors')
user.information.department=a_form.cleaned_data.get('department')
user.information.nationality=a_form.cleaned_data.get('nationality')
user.information.date_of_birth=a_form.cleaned_data.get('date_of_birth')
user.information.passport_number=a_form.cleaned_data.get('passport_number')
user.information.phone_number=a_form.cleaned_data.get('phone_number')
user.information.sex=a_form.cleaned_data.get('sex')
user.save()
information.save()
# for this type user input is for for username,last,first and email is registered
# form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('login')
else:
form = UserRegisterForm()
a_form = InformationForm()
context={'form':form,'a_form':a_form }#,'a_form':a_form
return render(request, 'student/register.html', context)
#login_required
def profile(request):
return render(request, 'student/profile.html')#,context
#login_required
def profile_update(request):
if request.method == 'POST':
u_form=UserUpdateForm(request.POST,instance=request.user)
i_form=InformationUpdateForm(request.POST,request.FILES,instance=request.user.information)
if u_form.is_valid() and i_form.is_valid():
u_form.save()
i_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('profile')
else:
u_form=UserUpdateForm(instance=request.user)
i_form=InformationUpdateForm(instance=request.user.information)
context={'u_form': u_form,
'i_form':i_form}
return render(request, 'student/profile_update.html',context)
models.py
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
# CHOICES=[('M','Male'),
# ('F','Female')]
class Information(models.Model):
M='Male'
F='Female'
SELECT_GENDER_CHOICE=[(M, 'Male'),
(F, 'Female')]
########################################################
B='Bachelors'
Ma='Masters'
P='PhD'
SELECT_DEGREE_CHOICE=[(B, 'Bachelors'),
(Ma, 'Masters'),(P, 'PhD')]
#########################################################
Y1='1 year'
Y2='2 year'
Y3='3 year'
Y4='4 year'
Y5='5 year'
SELECT_YEARS_CHOICE=[(Y1, '1 year'),(Y2, '2 year'),(Y3, '3 year'),(Y4, '4 year'),(Y5, '5 year')]
user = models.OneToOneField(User,null=True,on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='student')
nationality=models.CharField(max_length=120,blank=False)
sex=models.CharField(max_length=8,choices=SELECT_GENDER_CHOICE,default=M)
department=models.CharField(max_length=120,blank=False)
years=models.CharField(max_length=120,blank=False,choices=SELECT_YEARS_CHOICE,default=Y1,null=True)
degree=models.CharField(max_length=120,blank=False,choices=SELECT_DEGREE_CHOICE,null=True)
majors=models.CharField(max_length=500,blank=False)
phone_number=models.CharField(max_length=12,blank=False)
passport_number=models.CharField(max_length=50,blank=False)#unique=True)
date_of_birth=models.CharField(max_length=10,blank=False)
report=models.FileField(default='StudentResults/DEFAULT_SHEET.xlsx',upload_to='StudentResults',max_length=500,blank=True)#,null=True
reg_no=models.CharField(max_length=10,null=True,unique=True)
def __str__(self):
return f'{self.passport_number} Information'
def save(self,*args, **kwargs):
super().save(*args, **kwargs)
img=Image.open(self.image.path)
if img.height>300 or img.width>300:
output_size=(300,300)
img.thumbnail(output_size)
img.save(self.image.path)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Information
# CHOICES=[('M','Male'),
# ('F','Female')]
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'}))
first_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'First name'}))
last_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Last name'}))
password1 = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
password2 = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Confirm'}))
class Meta:
model = User
fields = ['username','first_name','last_name', 'email', 'password1', 'password2']
class InformationForm(forms.ModelForm):
#sex=forms.ChoiceField(choices=CHOICES)
department = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Department'}))
majors = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Majors'}))
nationality = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Nationality'}))
date_of_birth = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Date of birth'}))
passport_number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Passport number'}))
phone_number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Phone number'}))
class Meta:
model=Information
fields=['department','majors','degree','years','nationality','date_of_birth','passport_number','phone_number','sex']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['email']
# def email(self):
# email = self.cleaned_data.get("email")#this gets the default title but does not override the required field
# #you can have multiple nested if else/elif statements. You can use this for email validation
# if not ".com" in email:
# raise forms.ValidationError("This is not a email")
# else:
# return email
class InformationUpdateForm(forms.ModelForm):
class Meta:
model=Information
fields=['phone_number']
signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Information
#receiver(post_save,sender=User)
def create_information(sender,instance,created,**kwargs):
if created:
Information.objects.create(user=instance)
#receiver(post_save,sender=User)
def save_information(sender,instance,**kwargs):
instance.information.save()
student-profile-page
{% extends "student/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.information.image.url }}">
<div class="media-body">
<p class="text-secondary">Username: {{ user.username }}</p>
<p class="text-secondary">First Name: {{ user.first_name }}</p>
<p class="text-secondary">Last Name: {{ user.last_name }}</p>
<p class="text-secondary">Email: {{ user.email }}</p>
<p class="text-secondary">Passport Number: {{ user.information.passport_number }}</p>
<p class="text-secondary">Date of Birth: {{ user.information.date_of_birth }}</p>
<p class="text-secondary">Sex: {{ user.information.sex }}</p>
<p class="text-secondary">Phone Number: {{ user.information.phone_number }}</p>
<p class="text-secondary">Nationality: {{ user.information.nationality }}</p>
<p class="text-secondary">Majors: {{ user.information.majors }}</p>
<p class="text-secondary">Depatrment: {{ user.information.department }}</p>
<p class="text-secondary">Results: {{ user.information.result }}</p>
<p class="text-secondary">Years: {{ user.information.years }}</p>
<p class="text-secondary">Degree: {{ user.information.degree }}</p>
<a class="btn btn-outline-info" href="{{ user.information.report.url}}">Download your Report</a>
</div>
</div>
{% comment %} <form method="POST">
{% csrf_token %}
<fieldset class="form-group" enctype="multipart/form-data">
<legend class="border-bottom mb-4">Profile Info</legend>
{{ i_form|crispy }}
{{ u_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update</button>
</div>
</form>
</div> {% endcomment %}
{% endblock content %}
That is because you are saving a_form.save() then again saving user.information.save(). You need to change the code like this:
user = form.save()
information = a_form.save(commit=False)
information.user = user
information.save()
messages.success(request, 'Your account has been created! You are now able to log in')
return redirect('login')
You can remove the rest of the code regarding user.information and remove the signals as well. You do not need signals to create Information instance because you have forms to do that.
You are getting double instance of user because of create_information signal.
user = form.save() in following code will save a User instance.
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
a_form =InformationForm(request.POST)
if form.is_valid() and a_form.is_valid():
# form.save() creates a user, and triggers create_information signal
user = form.save()
information = a_form.save()
Now, you have a signal create_information, which is triggered after a User instance is saved (this signal is a post_save singal).
Your user = form.save() will create a user, and will triggers create_information signal.
#receiver(post_save,sender=User)
def create_information(sender,instance,created,**kwargs):
if created:
Information.objects.create(user=instance)
This save another instance of Information, and since Information model has OneToOne mapping to User, another User instance is also saved.
Side note: You have three Information instances saved as well. One created by create_information signal, one by save_information signal, and third by a_form.save() method. This number can be more if cyclic signals are triggered, but not sure about that, so you'll have to check that by yourself.
Solution:
Firstly, get rid of all singals.
Secondly, add User to Information instance before saving it.
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
a_form =InformationForm(request.POST)
if form.is_valid() and a_form.is_valid():
user = form.save()
information = a_form.save(commit=False)
information.user = user
information.save()

Django form not displaying name and email fields

I am trying to learn how to use the User class and have made a form, but cant get it to display the email, first_name and last_name fields, I have the following code:
forms.py:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
class Meta:
model = User
fields = (
'username',
'email',
'first_name'
'password1',
'password2'
)
def save(self, commit = True):
user super(UserCreationForm, self).save(commit = False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm
def index(request):
return HttpResponse('index page')
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('accounts')
else:
form = UserCreationForm()
return render(request, 'accounts/register.html', {'form': form})
# Create your views here.
register.html:
{% extends 'accounts/base.html' %}
{% block head %}
<title> Sign Up</title>
{% endblock %}
{% block body %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
</form>
{% endblock %}
When I go to /accounts/register a form with username, password and password confirmation fields appear and the form works and saves to the database. But where are the first_name, last_name, email fields inlcuded in the User model?
Use RegistrationForm instead of UserCreationForm in your views
replace
from django.contrib.auth.forms import UserCreationForm
to
from .forms import RegistrationForm
form = RegistrationForm()