Django template won't render form errors - python

After a user has submitted a form with data that fails validation, form.errors in fact collects those errors as I've been debugging the issue. However when I render the page after a POST request, the errors will not be parsed in HTML alongside the fields where errors occur.
In other words <ul class="errorlist"> won't render in the html.
What needs to change in order for the validation errors to render in the template when user data doesn't pass validation?
# view that renders the template
#login_required(login_url="/accounts/sign_in/")
def new_profile(request, username):
form = ProfileForm()
import pdb; pdb.set_trace()
if request.method == 'POST':
user_profile = ProfileForm(request.POST)
if user_profile.is_valid():
user_profile.cleaned_data.update(user=request.user)
Profile.objects.create(**user_profile.cleaned_data)
return HttpResponseRedirect(
reverse("accounts:profile", kwargs={'username': username})
)
return render(request, 'accounts/create_profile.html', {'form': form})
# create_profile.html
{% extends 'layout.html' %}
{% block body %}
<form action="{% url 'accounts:new_profile' username=user %}" method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
{% endblock %}
-> if request.method == 'POST':
(Pdb) n
-> user_profile = ProfileForm(request.POST)
(Pdb) n
-> if user_profile.is_valid():
(Pdb) p user_profile.errors
{'birth': ['Enter a valid date.'], 'bio': ['Add more detail to your bio.']}
(Pdb) p user_profile.as_p()
# As shown when calling .as_p() in the console
<ul class="errorlist">
<li>Enter a valid date.</li>
</ul>
<p>
<label for="id_birth">Birth:</label>
<input id="id_birth" name="birth" placeholder="None" type="text" value="12-23" />
</p>
<ul class="errorlist">
<li>Add more detail to your bio.</li>
</ul>
<p><label for="id_bio">Bio:</label>
<input id="id_bio" name="bio" placeholder="None" type="text" value="Comments" />
</p>
<p><label for="id_avatar">Avatar:</label> <input id="id_avatar" name="avatar" placeholder="None" type="file" /></p>

Supply the form back to the user if it is not valid..
else:
form = ProfileForm()
#login_required(login_url="/accounts/sign_in/")
def new_profile(request, username):
import pdb; pdb.set_trace()
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
form.cleaned_data.update(user=request.user)
Profile.objects.create(**form.cleaned_data)
return HttpResponseRedirect(
reverse("accounts:profile", kwargs={'username': username})
)
else:
form = ProfileForm()
return render(request, 'accounts/create_profile.html', {'form': form})

Related

Why my form not sowing any validation errors after i click the submit button in django?

I've two forms rendering in a single function based view, it is diplaying validation errors of only one form when i click the signup button but when i click the login button it just reload my page
and doesn't showing any validation error
views.py
def register(request):
form = RegisterForm()
form_b = LogInForm()
if request.POST.get('submit') == 'sign_up':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
elif request.POST.get('submit') == 'log_in':
form1 = LogInForm(request=request, data=request.POST)
if form1.is_valid():
uname = form1.cleaned_data['username']
upass = form1.cleaned_data['password']
user = authenticate(username=uname, password=upass)
if user is not None:
login(request, user)
return redirect('/shop/')
else:
form = RegisterForm()
form_b = LogInForm()
return render(request, 'reg.html', {'form': form, 'form1': form_b})
forms.py
from distutils.command.clean import clean
from xml.dom import ValidationErr
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
password1 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username', 'email']
class LogInForm(AuthenticationForm):
username = forms.CharField(widget=forms.TextInput())
password = forms.CharField(widget=forms.PasswordInput())
reg.html
<form class="loginForm" action="" method="POST" novalidate>
{% csrf_token %}
{% for field in form %}
<p> {{field.label_tag}} {{field}} </p>
<p> {{field.errors}} </p>
{% endfor %}
<button type="submit" class="btnLogin" name='submit' value='sign_up'>Sign Up</button>
</form>
<form class="loginForm" action="" method="post" novalidate>
{% csrf_token %}
{% for field in form1 %}
<p> {{field.label_tag}} {{field}} </p>
<p> {{field.errors | striptags}} </p>
{% endfor %}
<button class="btnLogin" type="submit" name='submit' value='log_in'>Log In </button>
</form>
Try to create seperate view for both register and login.
try this way:
views.py:
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid:
form.save()
username = form.cleaned_data.get('username')
# messages.success(request,f'Welcome { username }')
return HttpResponseRedirect('/users/')
else:
form = RegisterForm()
return render(request,'users/register.html',{'form':form})
And in urls.py:
path('login',auth_views.LoginView.as_view(template_name='users/login.html'),name='login'),

how can I use LoginView in my own view and show in HTML templates?

I want to use ready Django LoginView, but in the same time I have to use my own view for registration in same HTML template. If in urls.py file I will connect 2 views than i will connect only first. So my question is that how can use LoginView in my own view and use 2 forms with jinja?
here is my views.py file and html ;)
def index(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
if 'signup' in request.POST:
if form.is_valid():
form.supervalid()
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Dear {username} you have been created a new accound!')
return redirect('main')
elif 'login' in request.POST:
if formlog.is_valid():
formlog.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('main')
else:
form = UserRegisterForm()
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
# this code is not working , but not returning any errors
HTML
{% if not user.is_authenticated %}
<!-- Login -->
<div class="container">
<div class="log-1">
<div class="log-0">
<p class="logtitle">BareTalk</p>
<form method="POST" name="login">
{% csrf_token %}
{{ formlog|crispy }}
<button class="log-button first" type="submit">Login</button>
</form>
<button class="log-button second"
onclick="modalwindowops.open();" id="signup">Sign Up</button>
</div>
</div>
</div>
<!-- Signup -->
<div class="modal-overlay">
<div class="modal-window">
<span class="close-modal" onclick="modalwindowops.close();">×</span>
<form method="POST" name="signup">
<p>Sign Up</p>
{% csrf_token %}
{{ form|crispy }}
<button type="submit">Sign Up</button>
</form>
</div>
</div>
{% else %}
<h1>Welcome back Amigo!</h1>
{% endif %}
Neither if 'signup' in request.POST: nor elif 'login' in request.POST: is triggered in your index() view because your HTML forms do not actually contain those inputs. Note that the name attribute is deprecated for the <form> element.
Instead you can add a hidden <input> inside your forms, like this:
<form method="POST">
{% csrf_token %}
{{ formlog|crispy }}
<input type="hidden" name="login" value="true" />
<button class="log-button first" type="submit">Login</button>
</form>
Also,
formlog = auth_views.LoginView.as_view(template_name='main/index.html')
saves a view to formlog, not a form, so calling formlog.is_valid() will cause an error.
Instead of
elif 'login' in request.POST:
if formlog.is_valid():
formlog.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('main')
you probably will only need to do
elif 'login' in request.POST:
log_view = auth_views.LoginView.as_view(template_name='main/index.html')
log_view(request)
Calling is_valid(), save(), and doing the redirect is all done by LoginView already. If you want to still do the custom message.success() you will have to override one or more of the LoginView methods, but that is another topic.
Update:
You also need to change this line in the view: formlog = auth_views.LoginView.as_view(template_name='main/index.html') (before return render...) to:
formlog = AuthenticationForm(request)
Take this line outside of the else block.
Also add the import for the form at the top of your views.py:
from django.contrib.auth.forms import AuthenticationForm
This change is required because the template needs the form object (which is AuthenticationForm for LoginView by default) instead of the view object. The updated view function will look like:
from django.contrib.auth.forms import AuthenticationForm
def index(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if 'signup' in request.POST:
if form.is_valid():
form.supervalid()
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Dear {username} you have been created a new accound!')
return redirect('main')
elif 'login' in request.POST:
log_view = auth_views.LoginView.as_view(template_name='main/index.html')
log_view(request)
else:
form = UserRegisterForm()
formlog = AuthenticationForm(request)
return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
Note that this can be improved by providing feedback when the login credentials are invalid. As it is, this updated code only reloads a blank login form if the provided credentials don't work.

why my login authentication is not working ? this code is neither redirecting me anywhere nor showing me any error

def login(request):
if request.method=='POST':
user = auth.authenticate(username=request.POST['username'],password=request.POST['password1'])
if user is not None:
auth.login(request,user)
return redirect('../')
else:
return render(request,'login.html',{'error':'username or password is wrong'})
else:
return render(request,'login.html')
You need to define your login form that is to be passed to the template.
For example:
forms.py
class LoginForm(forms.Form):
username = forms.CharField(label='Your Email/Username', max_length=100)
password = forms.CharField(label='Your Password', max_length=100)
Then in your views.py, you can define a view function as:
views.py
from .forms import LoginForm
def login(request):
if request.method == "POST":
if form.is_valid:
user = auth.authenticate(username=request.POST['username'],password=request.POST['password1'])
if user is not None:
auth.login(request,user)
return redirect('../')
else:
return render(request,'login.html',{'form': form, 'error':'username or password is wrong'})
else:
form = LoginForm()
return render(request,'login.html', {'form': form})
Then in your template, you can render the form as:
<form method="post">
{% csrf_token %}
{{ form.as_p }} <--render the form in other ways as preferred-->
{% for error in form.errors %} //for displaying the fields where errors have occured
{{ error }}
{% endfor %}
<button type="submit">Login</button>
</form>
you can use django inbuilt loginview:-
in urls.py
from django.contrib.auth.views import LoginView
urlpatterns =[
path('login/' , LoginView.as_view(template_name='login.html') , name ='login')
]
in ur login.html
<h1> login page!! </h1>
<form method='POST'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Login'>
</form>

Django, form is_valid() is always false

I'm learning Django and have some troubles with forms. I try to create a simple form where I type a name and show it on another page. But is_valid() always returns false. Please, help me to find my error
forms.py
from django import forms
class OrderForm(forms.Form):
user=forms.CharField(max_length=100)
views.py
def order(request):
return render(request, 'myapp/order.html', {})
def contact(request):
username='not logged'
if request.method == 'POST' :
form=OrderForm(request.POST)
if form.is_valid():
username=form.cleaned_data['username']
else:
username='not worked'
else:
form=OrderForm()
return render(request, 'myapp/contacts.html', {'username':username})
order.html
<form name = "form" action = "{% url 'contact' %}" method = "POST" >
{% csrf_token %}
<input type="text" name="username" placeholder="Name">
<button type="submit">Login</button>
</form>
contacts.html
You are : <strong>{{ username }}</strong>
Your form control has the name username in HTML, while your form's field is named user in Django. Thus, nothing is set in the form field.
Normally you'd put the form into the context and then render it either as {{ form }} or the like, or render each field, rather than build your own form controls. The docs show how: https://docs.djangoproject.com/en/1.10/topics/forms/#working-with-form-templates
views.py
from forms import OrderForm
def order(request):
form = OrderForm()
return render(request, 'myapp/order.html', {"form" : form})
order.html
<form name = "form" action = "{% url 'contact' %}" method = "POST" >
{% csrf_token %}
{{form.as_p}}
<button type="submit">Login</button>
</form>
At the time of rendering template {{form.as_p}} looks like
<p><label for="id_username">Username:</label>
<input id="id_username" type="text" name="username" maxlength="100" required /></p>

Django how to process content of either form or the other?

A user is able submit a POST request. Either by uploading a file or by using a sample on the server. Posting the file works perfect but I have trouble implementing the second part. This is my model:
class UploadFileForm(forms.Form):
file = forms.FileField()
from_server = forms.BooleanField(required=False,initial=False)
My template. I thought it best to use two forms. But I fail to check on the content/type/key of the incoming data in my view.
<div class="fieldWrapper">
<form action="flot" enctype="multipart/form-data" method="post">{% csrf_token %}
<label for="id_file">File:</label>
{{ form.file }}
<input id="upload" type="submit" value="Upload">
</form>
</div>
<div class="fieldWrapper">
<form action="flot" method="post">{% csrf_token %}
<label for="id_from_server">Gebuik een sample file op de server</label>
{{ form.from_server }}
<input id="server" type="submit" value="Go" name="Go">
<!--<input id="upload" type="submit" value="Go">-->
</form>
</div>
Here is my view. I don't know exactly how to check the incoming data on from which form they where submitted. See request.POST.getlist('Go') for my final attempt. Test-wise I will return a Http404.
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
if 'Go' in request.POST.getlist('Go'):
raise Http404
else:
err, line_z1, line_z2 = handle_uploaded_file(request.FILES['file'])
if err == None:
return render_to_response('flot.html',
{
'form': form,
'line1':simplejson.dumps(line_z1),
'line2':simplejson.dumps(line_z2)
},
context_instance=RequestContext(request))
else:
form = UploadFileForm()
return render_to_response('flot.html',
{'form': form,
'error': err
},
context_instance=RequestContext(request))
else:
form = UploadFileForm()
return render_to_response('flot.html',
{'form': form},
context_instance=RequestContext(request))

Categories

Resources