I have a form for registration. When I try to register, it does and everything is fine, just that, its now showing any Form Validation Errors in the template, when there should be.
forms.py:
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
import re
from django.core.exceptions import ObjectDoesNotExist
class UserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'username',)
username = forms.EmailField(label='Email', max_length=250)
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = user.username
user.save()
return user
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('Password do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w[\w.]*#[\w.]+$', username):
raise forms.ValidationError('Please enter a valid email address.')
try:
User.objects.get(username=username)
except ObjectDoesNotExist:
return username
raise forms.ValidationError('Email address is already taken.')
views.py:
def register_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
else:
print form.is_valid()
print form.errors
args = {}
args.update(csrf(request))
args['form'] = UserCreationForm()
print args
return render_to_response('register.html', args)
register.html:
{% extends "base.html" %}
{% block content %}
<h1>Registration:</h1>
<form method="post" action=".">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Register" />
</form>
{% endblock %}
I even tried {% if form.errors %}:
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>{{form.errors }}</p>
{% endif %}
<h1>Registration:</h1>
<form method="post" action=".">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Register" />
</form>
{% endblock %}
But with no luck. I think I am missing something.
The reason is, if there are errors, you are overwriting it with form=UserCreationForm()
Basically, if if form.is_valid() is False, you need to send the form unaltered. By calling form=UserCreationForm after form.is_valid() you are overriding the errors
Try this:
def register_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
else:
print form.is_valid()
print form.errors
else:
form = UserCreationForm()
return render_to_response('register.html', {'form': form}, context_instance=RequestContext(request))
Related
I modified the first password reset page successfully. (Where the user insert his email address)
Where it doesn't work it the Password Reset Confirm page (Where the users write his new password). When I click the link that I received by email to reset the password, it load my html template but it doesn't load my form. (Only load h1 tag and other things)
html template
{% load static %}
<div class="box" align="center">
<h1>Write your new password</h1>
<div class="small-line"></div>
<form method="POST">
{% csrf_token %}
{{ context.as_p }}
<button type="submit" class="sendbut">Reset Password</button>
</form>
</div>
forms.py
class SetPasswordForm(forms.Form):
def __init__(self, *args, **kwargs):
super(SetPasswordForm, self).__init__(*args, **kwargs)
# …
new_password1 = forms.CharField(
label=("New password"),
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
strip=False,
help_text=password_validation.password_validators_help_text_html(),
)
new_password2 = forms.CharField(
label=("New password confirmation"),
strip=False,
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
)
views.py
#sensitive_post_parameters()
#never_cache
def PasswordResetConfirmView(request, uidb64=None, token=None,
template_name='users/password_reset_confirm.html',
token_generator=default_token_generator,
set_password_form=SetPasswordForm,
post_reset_redirect=None,
current_app=None, extra_context=None):
"""
View that checks the hash in a password reset link and presents a
form for entering a new password.
"""
UserModel = get_user_model()
assert uidb64 is not None and token is not None # checked by URLconf
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_complete')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
try:
# urlsafe_base64_decode() decodes to bytestring on Python 3
uid = force_str(urlsafe_base64_decode(uidb64))
user = UserModel._default_manager.get(pk=uid)
except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
user = None
if user is not None and token_generator.check_token(user, token):
validlink = True
title = ('Enter new password')
if request.method == 'POST':
form = set_password_form(user, request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(post_reset_redirect)
else:
form = set_password_form(user)
else:
validlink = False
form = None
title = ('Password reset unsuccessful')
context = {
'form': form,
'title': title,
'validlink': validlink,
}
if extra_context is not None:
context.update(extra_context)
if current_app is not None:
request.current_app = current_app
return TemplateResponse(request, template_name, context)
urls.py
urlpatterns = [
path('password_reset/', views.password_reset, name='password_reset'),
path('password_reset/done/', views.password_reset_done, name="password_reset_done"),
path(r'reset/<uidb64>/<token>/', views.PasswordResetConfirmView, name='password_reset_confirm'),
]
please write {{form.as_p}} insted of {{context.as_p}}
{% load static %}
<div class="box" align="center">
<h1>Write your new password</h1>
<div class="small-line"></div>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="sendbut">Reset Password</button>
</form>
</div>
error messages are not working in Django templates.
after add error code in html template it shows no error message in webapp when fields are empty and press on submit button. html5 error is "novalidate" in template.
ValueError at /signup/
The view blog.views.user_signup didn't return an HttpResponse object. It returned None instead.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UsernameField
from django.contrib.auth.models import User
from django.utils.translation import gettext,gettext_lazy as _
class SignUpForm(UserCreationForm):
password1 = forms.CharField(label='Password',widget=forms.PasswordInput(attrs={'class':'form-control'}))
password2 = forms.CharField(label='Confirm Password(again)',widget=forms.PasswordInput(attrs={'class':'form-control'}))
class Meta:
model = User
fields = ['username','first_name','last_name','email']
labels = {'username':'Username','first_name':'First Name','last_name':'Last Name','email':'Email'}
widgets = {'username':forms.TextInput(attrs={'class':'form-control'}),
'first_name':forms.TextInput(attrs={'class':'form-control'}),
'last_name':forms.TextInput(attrs={'class':'form-control'}),
'email':forms.EmailInput(attrs={'class':'form-control'}),}
class LoginForm(AuthenticationForm):
username = UsernameField(widget=forms.TextInput(attrs={'autofocus':True, 'class':'form-control'}))
password = forms.CharField(label=_('password'),strip=False, widget=forms.PasswordInput(attrs={'autocomplete':'current-password','class':'form-control'}))
signup.html
{% extends 'blog/base.html' %}
{% load static %}
{% block content %}
<div class="col-sm-10">
<h3 class="text-white my-5">Signup Page</h3>
<form action="" class="post" novalidate>
{% csrf_token %}
{% for fm in form %}
<div class="form-group">
{{fm.label_tag}} {{fm}} {{fm.errors | striptags}}
</div>
{% endfor %}
<input type="submit" value='Submit' class='btn btn-primary'>
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p> {{error}} </p>
{% endfor %}
{% endif %}
</form>
</div>
{% endblock content %}
views.py
from django.shortcuts import render,HttpResponseRedirect
from django.contrib import messages
# Create your views here.
# home
def home(request):
return render(request, 'blog/home.html')
# about
def about(request):
return render(request, 'blog/about.html')
# contact
def contact(request):
return render(request, 'blog/contact.html')
# Dashboard
def dashboard(request):
return render(request, 'blog/dashboard.html')
# Logout
def user_logout(request):
return HttpResponseRedirect('/')
# Signup
def user_signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
messages.success(request, 'Congratulations You have become an Author.')
form.save()
else:
form = SignUpForm()
return render(request, 'blog/signup.html',{'form':form})
# Login
def user_login(request):
form = LoginForm()
return render(request, 'blog/login.html', {'form':form})
You need to handle GET and POST request :
def user_signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
messages.success(request, 'Congratulations You have become an Author.')
form.save()
else:
form = SignUpForm()
return render(request, 'blog/signup.html',{'form':form})
Please make sure to use POST method in your html :
<form action="" method="POST" class="post" novalidate>
...
</form>
I am building a register form, but I am having some trouble with its validation.
I would like to see the error message showing up at the field, but instead I am getting a error on the browser saying :
The User could not be created because the data didn't validate.
Request Method: POST
Request URL: http://127.0.0.1:8000/account/register/
Django Version: 1.9.8
Exception Type: ValueError
Exception Value:
The User could not be created because the data didn't validate.
Exception Location: C:\Python34\lib\site-packages\django\forms\models.py in save, line 446
This is my forms.py
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', required=False ,widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', required=False ,widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'first_name', 'email')
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
#cd = self.cleaned_data
if not password2:
raise forms.ValidationError("Fill out the password2 .")
if password1 != password2:
raise forms.ValidationError("The two password fields didn't match.")
return password2
This is my view register
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid:
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
return render(request, 'account/register_done.html', {'new_user': new_user})
else:
print (user_form.errors)
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
my htmls - register.html
{% extends "account/base.html" %}
{% block title %}Create an account{% endblock %}
{% block content %}
<h1>Create an account</h1>
<p>Please, sign up using the following form:</p>
<form action="." method="post">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Create my account"></p>
</form>
{% endblock %}
register_done.html
{% extends "account/base.html" %}
{% block title %}Welcome{% endblock %}
{% block content %}
<h1>Welcome {{ new_user.first_name }}!</h1>
<p>Your account has been successfully created. Now you can log in.</p>
{% endblock %}
Seems like you are not calling is_valid method, this may cause this issue:
if user_form.is_valid
Try to change above line to:
if user_form.is_valid()
I am using Learning Website Development with Django book.
I have downloaded the source code from the fallowing path Source code in github. I am able to run the application in my windows machine.
However for some reason whenever login or registration from contains errors after submit, these errors are not shown in the html page.
Kindly let me know what is the issue. One obeseration what I saw in the browser console is
Following line of code displays error message
def register_page(request):
form = RegistrationForm(request.POST or None)
print request.method
if request.method == 'POST' and form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {'form': form})
print variables
return render_to_response('registration/register.html', variables)
registration page html code:
{% extends "base.html" %}
{% block title %}User Registration{% endblock %}
{% block head %}User Registration{% endblock %}
{% block content %}
print "ddd"
{% if form.has_errors %}
<p>Your username and password didn't match.
Please try again.</p>
{% endif %}
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="register" />
</form>
{% endblock %}
Login page code:
{% extends "base.html" %}
{% block title %}User Login{% endblock %}
{% block head %}User Login{% endblock %}
{% block content %}
{% if form.has_errors %}
<p>Your username and password didn't match.
Please try again.</p>
{% endif %}
<form method="post" action="">
{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="submit" value="login" />
<input type="hidden" name="next" value="/" />
</form>
{% endblock %}
form.py
import re
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.models import User
from django import forms
class RegistrationForm(forms.Form):
print forms.Form;
username = forms.CharField(
label='Username',
max_length=30
)
email = forms.EmailField(
label='Email'
)
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput()
)
password2 = forms.CharField(
label='Password (Again)',
widget=forms.PasswordInput()
)
# password validation:
def cleaned_password2(self):
# all valid values are accessible trough self.clean_data
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.')
# username validation
def cleaned_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 ObjectDoesNotExist:
return username
raise forms.ValidationError('Username is already taken.')
class BookmarkSaveForm(forms.Form):
url = forms.URLField(
label='URL',
widget=forms.TextInput(attrs={'size': 64})
)
title = forms.CharField(
label='Title',
widget=forms.TextInput(attrs={'size': 64})
)
tags = forms.CharField(
label='Tags',
widget=forms.TextInput(attrs={'size': 64})
)
http://localhost:8000/static/style.css Failed to load resource: the server responded with a status of 404 (Not Found)
The code is simply wrong.
By combining the method == 'POST' and form.is_valid() into one check, they're ensuring that a new - empty - form is created if either of those things are false. What they should be doing is only creating an empty form if method does not equal "POST"; if the form is not valid, they need to return that invalid form to the template, as it contains the errors.
So you need to follow the normal pattern, with two separate if statements:
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']
)
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {'form': form})
I Remenber i got the same problem, the thing i did is:
Use self.add_error to attach errors to a specific field in the form. Call add_error() instead of forms.ValidationError(), like this:
password validation:
def cleaned_password2(self):
# all valid values are accessible trough self.clean_data
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
msg = 'Passwords do not match.'
self.add_error('password1',msg)
This is my view:
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
and this is my main_page.html:
{% if form.errors %}
<p>NOT VALID</p>
{% for errors in form.errors %}
{{ errors }}
{% endfor %}
{% endif %}
<form method="post" action="/">{% csrf_token %}
<p><label for="id_username">Username:</label>{{ form.username }}</p>
<p><label for="id_email">Email Address:</label>{{ form.email }}</p>
<p><label for="id_password">Password:</label>{{ form.password1 }}</p>
<p><label for="id_retypePassword">Retype Password:</label>{{ form.password2 }}</p>
<input type="hidden" name="next" />
<input type="submit" value="Register" />
</form>
When I go to the url which uses the main_page view, it just displays the form. When I submit the form with errors (with blank fields and without a proper email address) it just redirects me to the same page and doesn't display any errors. It doesn't even say "NOT VALID".
When I change
{% if form.errors %}
to
{% if not form.is_valid %}
it always says "NOT VALID" (even if it is the first time going to the url and even if I didn't submit anything yet).
This is my RegistrationForm:
from django import forms
import re
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
email = forms.EmailField(label='Email')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput())
password2 = forms.CharField(label='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): #checks if all the characters in username are in the regex. If they aren't, it returns None
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
User.objects.get(username=username) #this raises an ObjectDoesNotExist exception if it doesn't find a user with that username
except ObjectDoesNotExist:
return username #if username doesn't exist, this is good. We can create the username
raise forms.ValidationError('Username is already taken.')
It is redirecting you because you always return HttpResponseRedirect if the method is POST, even if the form is not vaild. Try this:
def main_page(request):
form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
That way, the form instance, on which is_valid was called, is passed to the template, and it has a chance to display the errors. Only if the form is valid, the user is redirected. If you want to be fancy, add a message using the messages framework before redirecting.
If you want it a little bit more concise:
def main_page(request):
form = RegistrationForm(request.POST or None)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
Make your view something like this:
if form.is_valid():
pass
# actions
else:
# form instance will have errors so we pass it into template
return render(request, 'template.html', {'form': form})
And in the templates you can iterate over form.errors or simple:
{{ forms.as_p }}
You can reformat your view to display the form errors in the console as below
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
else:
print(form.errors)
return HttpResponse("Form Validation Error")
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
As always, keep the indent as above. If the form has any error , it will display in the console like
<ul class="errorlist"><li>date<ul class="errorlist"><li>Enter a valid date.</li></ul></li></ul>
Hope it helps