My login works fine except for not showing all errors. When i type an invalid username or password, these errors don't show and the page just refreshes without putting any errors down.
However when i leave one field blank, it shows the correct error:
So the missing errors are(from source):
error_messages = {
'invalid_login': _("Please enter a correct %(username)s and password. "
"Note that both fields may be case-sensitive."),
'inactive': _("This account is inactive."),
}
my code:
def login_user(request):
"""Logs a user into the application."""
auth_form = AuthenticationForm(None, request.POST or None)
# The form itself handles authentication and checking to make sure password and such are supplied.
if auth_form.is_valid():
(request, auth_form.get_user())
return HttpResponseRedirect(reverse('index'))
return render(request, 'login.html', {'auth_form': auth_form})
My template:
<form action="{% url 'login_user' %}" method="post" class="login">{% csrf_token %}
<div>
<input name="username" placeholder="Username:" type="text" name="username" value="" id="username" class="login">
{{ auth_form.username.errors }}
</div>
<div>
<input name="password" placeholder="Password:" type="password" name="password" value="" id="password" class="login">
{{ auth_form.password.errors }}
</div>
<div>
<center>
<a href="{% url 'register_user' %}">
register
</a>
<button type="submit" class="link">
login
</button>
</center>
</div>
</form>
what do i do wrong?
You aren't including form.non_field_errors in your template. See the docs on customizing the form template for an example.
As an aside, the AuthenticationForm takes the request as its first argument. It looks slightly strange that you are passing None instead of request.
Related
I tried to make some pages only visible when logged in.
I tried it with:
def backend(request):
if request.user.is_authenticated:
return render(request, 'web/backend-index.html')
else:
return redirect(reverse('web:login'))
and also with:
#login_required
def backend(request):
return render(request, 'web/backend-index.html')
The first code does not let me log in.
The second code does not let me log in but the url changes too:
http://127.0.0.1:8000/login/?next=/backend/
If I just render the view without checking if logged in, the login is working fine and I´ll be passed to the backend page.
The whole code is on github: https://github.com/psmaster1/BrainSystems/tree/master/smarthome/web
I don't get any error messages. It's just redirecting to the login page...
Your login form is incorrect - that's why you never actually authenticate. It was sending POST request to incorrect endpoint and it was not rendering actual form. This is how you can render fields manually
Change it to this:
<section class="login-form">
<div class="login-fields">
<h3>Login</h3>
<form method="POST">
{% csrf_token %}
<div class="form-group">
{{ login_form.username }}
<label for="{{ login_form.username.id_for_label }}" class="control-label">Username</label><i class="bar"></i>
{{ login_form.username.errors }}
</div>
<div class="form-group">
{{ login_form.password }}
<label for="{{ login_form.password.id_for_label }}" class="control-label">Passwort</label><i class="bar"></i>
{{ login_form.password.errors }}
</div>
<div class="button-container">
<input type="submit" class="button" value="Login" />
</div>
</form>
<p>Noch nicht Registriert?</p>
Registrieren
</div>
</section>
Already fixed it! The Problem was the action attribute in the form tag. It causes the troubles. Just removed it from the form tag and make a redirect in the login() method. Thanks guys! :)
I would like to call a function which is in /inscription/views.py since all views (because it's for the login). And I need to pass the username and the password in parameters to log the user.
def login_user(request):
if request.method =='POST':
auth_form=AuthenticationForm(data=request.POST)
if auth_form.is_valid():
username = request.POST.get('username')
password = request.POST.get('password')
uti = authenticate(username = username,password = password)
if uti:
if uti.is_active:
login(request, uti)
return HttpResponseRedirect('/accueil')
else:
return HttpResponse("Your account is disabled.")
else:
return HttpResponse("Invalid login details supplied.")
else:
auth_form=AuthenticationForm()
return render_to_response('authentication.html',
{'auth_form': auth_form}, RequestContext(request))
def logout_user(request):
logout(request)
And In my base.html I would like to add something like :
<label class="form_login">pseudo : </label>
<input type="text" name="username" id="id_username" class="login_input">
<label class="form_login">mot de passe : </label>
<input type="text" name="password" id="id_password" class="login_input">
<input value="login" type="submit"/>
<button>logout</button>
If I understand your question correctly, what you need is to force the user to login if he is not already logged in before he can access your views. To do this, all you need to do is to decorate your views with login_required decorator
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
...
From the docs:
login_required() does the following:
- If the user isn’t logged in, redirect to settings.LOGIN_URL, passing
the current absolute path in the query string. Example:
/accounts/login/?next=/polls/3/.
- If the user is logged in, execute the view normally. The view code is
free to assume the user is logged in.
Update:
From your comment, now I understand that you need to make a form in all pages for the user to login, or a logout link if he is already logged in. First you need to define your URLs for these views:
url(r'^login/$', 'inscription.views.login', name='auth_login'),
url(r'^logout/$', 'inscription.views.logout', name='auth_logout'),
And in your base.html:
{% if user.is_authenticated %}
Logout
{% else %}
<form method="post" action="{% url 'auth_login' %}">
{% csrf_token %}
<input type="text" name="username" id="id_username">
<input type="text" name="password" id="id_password">
<input type="submit" value="Log in" />
</form>
{% endif %}
As a side note, I highly recommend you to use one of these reusable apps for auth and registration. unless you have strange requirements.
http://django-registration-redux.readthedocs.org/en/latest/
http://django-allauth.readthedocs.org/en/latest/
The problem which you are facing is , that u want the login and logout to work from other pages also, So, for this you need not to go for any extra function. All you need to do is, u just extend your base.html to all other html pages. Then you will surely be able to login and logout from all the pages.
Suppose you have login/logout in base.html
<label class="form_login">pseudo :</label>
<input type="text" name="username" id="id_username" class="login_input">
<label class="form_login">mot de passe : </label>
<input type="text" name="password" id="id_password" class="login_input">
<input value="login" type="submit"/>
<button>logout</button>
Now make some other html say test.html
There at the beginning you write
{% extends 'base.html' %}
followed by your HTML markup.
Don't forget to use
{% block content %} {% endblock %} **template tags**
In base as well as other HTML pages.
In other pages u try to write the complete code in template tags.
For query https://docs.djangoproject.com/en/1.7/topics/templates/
Also try using the concept of decorator.
The following is all I have for the client server
<div>
<form action="/next/" role="form" method="POST">
{% csrf_token %}
<textarea class="form-control" rows="10"></textarea>
<input type="submit" value="submit"/>
</form>
</div>
and from the server(django) I just want to process the form.
def next(request):
request.body // nothing here except CSRF
request.POST // nothing here except CSRF
It's embarrassing, but what am I doing wrong?
It is not embarrassing. you just forgot name attribute in form element that you want to catch in backend.
<textarea name="element_name" class="form-control" rows="10"></textarea>
and in views.py
def next(request):
if request.method == "POST":
textarea_value = request.POST.get('element_name') # viola!
You forgot to add name attribute to the text area:
<textarea name="some_name" class="form-control" rows="10"></textarea>
Add a "name" attribute to the textarea ?
I am having login forms in all static pages. I have enabled csrf middleware in my project. Now when the user submits the form from http static page i get the error,
csrf verification failed
Is there a way to ensure cross site validation, even when posted from non-scure to secure page?
I want to neither add scrf exempt decorator nor change the page to https.
This is my template:
<form action='{{login_url}}' method = 'post'>
{% csrf_token %}
<div class="searchbox login">
<input autocomplete="off" id="id_fakeusername" type="text" name="fakeusername" maxlength="100" value='Email' style="color: #727272" onfocus="$('#id_fakeusername').hide();$('#id_username').show();
$('#id_username').focus();" />
<input autocomplete="off" type='text' id="id_username" type="text" name="username" maxlength="100" style="display: none" value='' onblur="if ($('#id_username').attr('value') == '') {$('#id_username').hide();$('#id_fakeusername').show();}" />
</div>
<div class="searchbox login">
<input autocomplete="off" id="id_fakepassword" type="text" name="fakepassword" maxlength="50" style="color: #727272" value='Password' onfocus="$('#id_fakepassword').hide(); $('#id_password').show(); $('#id_password').focus();" />
<input autocomplete="off" type='password' id="id_password" name="password" type="text" style="display: none" value='' onblur="if ($('#id_password').attr('value') == '') {$('#id_password').hide();$('#id_fakepassword').show();}" />
</div>
{% block nativewin %}
<div class="loginbut"><input type="submit" border="0" title="Login" value="Login" /></div>
{% endblock nativewin %}
</form>
From the CsrfViewMiddleware code [1]:
# Suppose user visits http://example.com/
# An active network attacker (man-in-the-middle, MITM) sends a
# POST form that targets https://example.com/detonate-bomb/ and
# submits it via JavaScript.
#
# The attacker will need to provide a CSRF cookie and token, but
# that's no problem for a MITM and the session-independent
# nonce we're using. So the MITM can circumvent the CSRF
# protection. This is true for any HTTP connection, but anyone
# using HTTPS expects better! For this reason, for
# https://example.com/ we need additional protection that treats
# http://example.com/ as completely untrusted. Under HTTPS,
# Barth et al. found that the Referer header is missing for
# same-domain requests in only about 0.2% of cases or less, so
# we can use strict Referer checking.
So I think the answer to your question is 'no', using the built-in protection!
[1] https://github.com/django/django/blob/master/django/middleware/csrf.py#L118
Did you included the {{ csrf_token }} in your template?
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Did you included a RequestContext in render_to_response?
from django.template import RequestContext
from django.shortcuts import render_to_response
return render_to_response('contact.html', {'form': form},
context_instance=RequestContext(request))
If it still not work, follow the steps as described in the docs.
Is there a way to identifying the validation error is associated with which form for a template contaning multiple forms?
Let me explain the scenario. I have login window popup script within my base.html
<div id="dialog1" class="window">
<form method="post" action="/accounts/login/?next=/IW/home" id='login-form' name=login-form>{% csrf_token %}
<div class="d-header">
{{ form.non_field_errors }}
<input type="text" name="username" id="id_username" value="" onclick="this.value=''"/><br/>
<input type="password" name="password" id="id_password" value="" onclick="this.value=''"/><br/>
<input type="hidden" name="login_form" value="1" />
<input type="submit" value="login" />
</div>
{% endif %}
</div>
</form>
</div>
<div id="mask"></div>
{% if form.non_field_errors %}
<script>
var maskHeight = $(document).height();
var maskWidth = $(window).width();
//Set heigth and width to mask to fill up the whole screen
$('#mask').css({'width':maskWidth,'height':maskHeight});
$('#mask').show();$('.window').show();
</script>
{% endif %}
As all other templates extends base,html whenever there is an error non_field error then login window pops up . I would like to show the login error only when login form is submit not on submit of someother form with a non field error.
For this I need to identify the name of the form.something like this {% ifequal form.form_name login_form %} - Display login error .Is this possible??
They isn't anything special about the name 'form' in the template. It's just a default context name, you can choose to name your forms anything you like.
Just name the forms differently in your context:
from django.http import Http404
def detail(request, poll_id):
# NOTE: This view code isn't really form processing code, just using it to show
# how you can pass different names into your template context.
login_form = MyLoginForm()
detail_form = MyDetailForm()
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p, 'login_form': login_form, 'detail_form': detail_form})
And then:
<div id="dialog1" class="window">
<form method="post" action="/accounts/login/?next=/IW/home" id='login-form' name=login-form>
{% csrf_token %}
<div class="d-header">
{{ login_form.non_field_errors }}
.
.
.
Also, if you want to do multiple instances of the same form type, have a look at formsets