I have a problem:
In my function register() I use FormRegistration of Django and my custom ProfilForm, but I cannot display the different errors (username not unique, passwords do not match, ...).
views.py
def register(request):
if request.method == 'POST':
form = UserCreate(request.POST)
form2 = ProfilForm(request.POST)
if form.is_valid() and form2.is_valid():
user = form.save()
form2 = form2.save(commit=False)
form2.user = user
form2.skill = form2.cleaned_data.get('skill')
form2.board = form2.cleaned_data.get('board')
form2.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('/accueil')
else:
form = UserCreate()
form2 = ProfilForm()
return render(
request,
'registration/register.html',
{'form2': form2},
{'form': form})
This is my template register.html for displaying errors :
{% if form.errors %}
<div class="alert alert-danger">
<p><strong>Error !</strong> <p>There was a problem while trying to register, check your fields.</p></p>
</div>
{% endif %}
{% if form.errors %}
<div class="alert alert-danger">
<p><strong>Error !</strong> <p>{{ form.username.errors|striptags }}</p></p>
</div>
{% endif %}
Any suggestions?
There are a few issues:
The line form2 = form2.save(commit=False) does not look right; you should assign the output of save() to another variable, but right now you are just overriding form2.
The last return statement should only get one dict for context:
Change you code
return render(
request,
'registration/register.html',
{'form2': form2},
{'form': form})
to
return render(
request,
'registration/register.html',
{'form2': form2, 'form': form})
Related
I was trying to create a blog app by following an online Django tutorial and while I was testing the sign-up page, I ran into a Value Error saying that the view did not return a HTTP response object. i tried everything but i could not find the answer as i am not a Django expert
in the users app's views.py file was the code that threw the error
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account Created for {username}')
return redirect('blog-home')
else:
form = UserCreationForm()
return render(request, 'users/register.html', {'form': form})
and this is the register template
{% extends "myblog/base.html" %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">
Join Today!
</legend>
{{ form.as_p }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">
Sign Up!
</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">
Already Have an account?
Sign In!
</small>
</div>
</div>
{% endblock content%}
And this is the file structure of the project
File Structure
If we have a POST request, and the form is not valid, you do not return anything. Unindent the render call, so:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST, request.FILES)
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account Created for {username}')
return redirect('blog-home')
else:
form = UserCreationForm()
return render(request, 'users/register.html', {'form': form})
You can write function like this ...
def register(request):
form = UserCreationForm()
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
messages.success(request, f'Account Created for {username}')
return redirect('blog-home')
else:
form.errors
context = {'form': form}
return render(request, 'users/register.html', context)
return something for the function register also , you are returning only in if else conditions
return render(request, 'users/register.html', {'form': form}) add this at the end of the function outiside if else (now we have returned something for the function register also , you are returning only in if else conditions
How can I show errors like email or username is already taken in this page Aaccounts/sign-up.html because when try to to put a username and this username is already taken the page only refresh without any message.
Before:
After:
Code:
class SignUpView(CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'Aaccounts/sign-up.html'
def login (request) :
if request.method=='POST':
passwordtest=request.POST ['password']
usernametest=request.POST ['username']
user=auth.authenticate(username=usernametest,password=passwordtest)
if user is not None :
auth.login(request,user)
current_user = request.user
correctUSER = get_object_or_404(CustomUser, pk=current_user.id)
need_to_cheack=correctUSER.main_affilitee
kain=False
if need_to_cheack !="":
objs=CustomUser.objects.all()
for aleratwar in objs:
if kain==False:
if aleratwar.username==need_to_cheack and aleratwar.afilliteuser==True and aleratwar.username !=correctUSER.username :
kain=True
if kain== False:
correctUSER.main_affilitee=''
correctUSER.save()
return redirect('home')
else:
return render(request,'Aaccounts/login.html',{'eroor':True})
else:
return render(request,'Aaccounts/login.html')
This is the simple example of showing the message. In your view you can In this way
from django.contrib import messages
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
messages.error(request,'username or password not correct')
return redirect('login')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
{{ message }}
</div>
{% endfor %}
and In your template:
{% for message in messages %}
<div class="alert alert-success">
<a class="close" href="#" data-dismiss="alert">×</a>
{{ message }}
</div>
{% endfor %}
The view ats.views.index didn't return an HttpResponse object. It returned None instead.
I am trying to implement an authentication system, if I enter the password correctly I don't bump into any problems but when I enter it incorrectly I get this error. Does anyone know how I could solve this?
This is my view
def index(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return render(request, "homepage.html", context_instance=RequestContext(request))
else:
form = AuthenticationForm()
return render(request, "index.html", {'form': form})
This is my html
{% block content %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Ats</h1>
{{ form }}
<input type="submit" name="" value="Login">
</form>
{% endblock %}
The request can be a POST request, but where the form.is_valid() does not hold. In that case, your view, will return None.
You should "unindent" the return render(..) part:
from django.shortcuts import redirect
def index(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('some-view-name')
else:
form = AuthenticationForm()
return render(request, 'index.html', {'form': form})
Note that here your view does not performs authentication. You should first check if the password (or some other token) matches. See the documentation on authenticate(..) [Django-doc] for more information.
In case of a successful POST request, you should make a redirect to implement the Post/Redirect/Get pattern [wiki].
Rearranging the code should work
def index(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return render(request, "homepage.html", context_instance=RequestContext(request))
return render(request, "index.html", {'form': form})
You are getting this problem because you haven't written a HttpResponse object if the form is not valid.
To overcome this in your view write return an HTTP response if the form is not valid.
def index(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return render(request, "homepage.html", context_instance=RequestContext(request))
else:
return render(request, "index.html", {'form': form, 'errors': form.errors})
else:
form = AuthenticationForm()
return render(request, "index.html", {'form': form})
in index.html
{% block content %}
{% if errors %}
{{ errors }}
{% endif %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Ats</h1>
{{ form }}
<input type="submit" name="" value="Login">
</form>
{% endblock %}
or you can simply handle conditions and return default request if the request is not a post request.
def index(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return render(request, "homepage.html", context_instance=RequestContext(request))
return render(request, "index.html", {'form': form})
You need to define the else condition if form is not valid.
def index(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return render(request, "homepage.html", context_instance=RequestContext(request))
else:
return render(request, "index.html", {'form': form, 'errors': form.errors})
else:
form = AuthenticationForm()
return render(request, "index.html", {'form': form})
In your template you can show form errors by accessing this context variable {{ errors }}.
{% block content %}
{% if errors %}
{{ errors }}
{% endif %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Ats</h1>
{{ form }}
<input type="submit" name="" value="Login">
</form>
{% endblock %}
I am not getting any errors in the template. It just gives me back the form without error. Although the uploading function works fine, but if I don't give any input it doesn't give me any errors. How would I get the errors if there are in my template?
html:
{% block content %}
<form action="/{{ user.username }}/upload_photos/" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Upload"/>
</form>
{% endblock %}
views.py:
def upload_photos(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
form = PhotoForm(request.POST, request.FILES)
if form.is_valid():
forum = form.save(commit=False)
forum.user = user
forum.save()
return HttpResponseRedirect('/'+user.username+'/photos')
else:
form = PhotoForm()
return render(request, 'upload_photos.html',{'form':form})
else:
form = PhotoForm()
return render(request, 'upload_photos.html',{'form':form})
I've commented out the line that empties your form.
def upload_photos(request, user_name):
user = User.objects.get(username=unquote(user_name))
if request.method=='POST':
form = PhotoForm(request.POST, request.FILES)
if form.is_valid():
forum = form.save(commit=False)
forum.user = user
forum.save()
return HttpResponseRedirect('/'+user.username+'/photos')
else:
# form = PhotoForm() Don't overwrite the submitted form.
return render(request, 'upload_photos.html',{'form':form})
else:
form = PhotoForm()
return render(request, 'upload_photos.html',{'form':form})
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