django allauth: redirecting for invalid passwords - django

I have a custom page which calls allauth signup view (custom_passcheck.html)
<form action="{% url 'account_signup' %}" method="post" class="form">
{% csrf_token %}
<BR>
<BR>
<BR>
<center>
<div class=signuponepage>
<div class=sign-up>
<div class=signup-box>
<div class="form-element email-address">
<label id="email-address-label">
<strong>
Create a password (it must be 6 characters long)
</strong>
<input type="hidden" name="username" value="{{ pemail }}">
<input type="hidden" name="email" value="{{ email }}">
<input type="text" maxlength="19" name="password1" value="" placeholder="Password">
<input type="text" maxlength="19" name="password2" value="" placeholder="Password (again)">
</label>
</div>
<div class="form-element nextstep-button">
{% buttons %}
<button type="submit" class="btn btn-primary btn-sm">
Finish {% bootstrap_icon "chevron-right" %}
</button>
{% endbuttons %}
</div>
</div>
</div>
</div>
</center>
</form>
Now, if a user puts in password less than 6 chars, it will raise an error and redirect the user to allauth signup page (/account/signup)
Question: instead of redirecting to (/account/signup), how can i redirect to the custom page (custom_passcheck.html) while preserving POST data

Related

Bootstrap not allows to post data from html in django

{% csrf_token %}
User name
</div>
<div class="form-group">
<label class="form-label" for="form2Example2">Password</label>
<input type="password" id="form2Example2" class="form-control" name="password" required/>
</div>
<button type="button" class="btn btn-primary btn-block mb-4">Sign in</button>
i try to post data like email id and password in post method , but it sent through get method . I think there may be problem with bootstrap. can u tell me what are the modifications to be done in the bootstrap for post data method.
thanks
If you want to send it as post, then use button type: "submit". Also you might need form section, if you don't have it. Like this:
<form method="POST">
{% csrf_token %}
<div class="form-group">
(...)
</div>
<button type="submit" class="btn btn-primary btn-block mb-4">Sign in</button>
</form>
You need to add method = "POST" with {% csrf_token %} and submit button
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label>Email address</label>
<input type="email" class="form-control">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Signin</button>
</form>

Django: Trouble with logging user using Bootstrap login.html

I'm using Django 3.0.2 + Boostrap. I have created a registration/login.html page. The contents of this page are shown below.
The page renders correctly and most of it works OK. However, I am unable to login to my website through this page. I keep getting Your username and password did not match. Please try again. I can login to the admin website without any issues if I use the same username/password. I am not sure what is wrong with my login.html. Any ideas?
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password did not match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account does nohave access to this page. To proceed,please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.html">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="register.html">Create an Account!</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Contents of views.py:
from django.contrib.auth import logout
def logout_view(request):
"""Log out user from the website."""
logout(request)
Your input types are missing the name attribute. As per the Mozilla docs:
A string specifying a name for the input control. This name is
submitted along with the control's value when the form data is
submitted.
So the name is submitted with the form. But what if there is no name attribute?
Same Documentation explains:
Consider the name a required attribute (even though it's not). If an
input has no name specified, or name is empty, the input's value is
not submitted with the form.
So your username and password are not sent to the backend.
You need to provide the name attributes to your input types.
<form class="user" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control form-control-user" id="exampleInputUserName" placeholder="Username" `name="username"`>
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user" id="exampleInputPassword" placeholder="Password" name="password">
</div>
<input type="submit" class="btn btn-primary btn-user btn-block" value="Login">
<input type="hidden" name="next" value="{{ next }}">
</form>
It is front-end issue, not particularly related to Django.

Django allauth override default template with custom template

I'm currently trying to override a Django allauth template. So far, I followed all the recommendations on similar questions to mine:
overriding default templates of django-allauth
How to override template in django-allauth?
However, my goal is just change the default Django allauth without making new views or forms. (In previous projects I used to override the default forms constructor classes with the helper of Django Crispy Forms which is not possible in this particular case.)
I believe there is a way to ignore the {{form}} variable and just define a working form from scratch. Currently, I have my template being successfully being displayed when I navigate to 'account_login'. However, when I press Sign In nothing happens.
Here is my myapp/templates/account/login.html file:
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}
Sign In to {{ SITE_NAME }}
{% endblock %}
{% block body %}
<div class="centered">
<img class="logo" src={% static 'imgs/logo.png' %} alt="" width="100" height="100">
<form id="login_form" class="form-signin" method="post" action="{% url 'account_login'%}">
{% csrf_token %}
<label for="inputLogin" class="sr-only">Email address or Username</label>
<input type="text" id="login" class="form-control" placeholder="Email or Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="password" class="form-control" placeholder="Password" required>
<div class="note mb-3">
<label>
<input type="checkbox" value="remember" id="remember"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<div class="note mb-3 text-center">
<p>Forgot? Retrieve your login.</p>
<p>Not registered? <a href={% url 'account_signup'%}>Sign Up!</a></p>
</div>
</form>
</div>
{% endblock %}
Yes, you can customize it the way you want. It is rather simple.
When you use {{ form.as_p }} the page renders the form. And if you inspect the form you will notice that the page rendered the following form:
notice the id="" and the name="" you have to name it the exact same.
With that your code should look like this:
<form id="login_form" class="form-signin" method="post" action="{% url 'account_login'%}">
{% csrf_token %}
<label for="inputLogin" class="sr-only">Email address or Username</label>
<input type="text" name="login" id="id_login" class="form-control" placeholder="Email or Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
<div class="note mb-3">
<label>
<input type="checkbox" name="remember" value="remember" id="id_remember"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<div class="note mb-3 text-center">
<p>Forgot? Retrieve your login.</p>
<p>Not registered? <a href={% url 'account_signup'%}>Sign Up!</a></p>
</div>
</form>
And you should be good to go.

How to show error messages in a custom signup template in Django

I'm trying to show error message in my custom signup template. Just to verify my below codes work, I used the {{ form.as_table }} and it shows error message properly. However, when I use my custom signup template, it doesn't show any error message when I cause an error on purpose on the signup form.
HTML
<form class="form-signin" method="POST">
{% csrf_token %}
<div class="container">
<div class="jumbotron">
<a class="navbar-brand js-scroll-trigger" href="{% url 'boutique:index' %}"><img width="165" height="30" src="{% static 'boutique/img/modvisor_logo_black.png' %}"></a>
<br><br>
<div class="text-center mb-4">
<h1 class="h3 mb-3 font-weight-normal">Join Modvisor</h1>
<p class="error-message">
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
{% endif %}
</p>
</div>
<div class="form-label-group">
<input type="text" id="inputEmail" class="form-control" name="username" placeholder="Email address" required autofocus>
<label for="inputEmail">Email</label>
</div>
<div class="form-label-group">
<input type="password" id="inputPassword1" class="form-control" name="password1" placeholder="Password" required>
<label for="inputPassword">Password</label>
</div>
<div class="form-label-group">
<input type="password" id="inputPassword2" class="form-control" name="password2" placeholder="Password" required>
<label for="inputPassword">Confirm Password</label>
</div>
<!--
<div class="form-label-group">
<input type="password" id="inputPassword" class="form-control" name="password2" placeholder="Password" required>
<label for="inputPassword">Confirm Password</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
-->
<button class="btn btn-success btn-block" type="submit">Sign Up</button>
<br>
<button class="btn btn-secondary btn-block" type="button">Back</button>
<p class="mt-5 mb-3 text-muted text-center">© 2018 Modvisor All Rights Reserved.</p></p>
</div>
</div>
</form>
forms.py
class SignupForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
fields = UserCreationForm.Meta.fields
views.py
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
form.save()
return redirect(settings.LOGIN_URL)
else:
form = SignupForm()
return render(request, 'accounts/register.html', {'form': form})
You should use form.errors.field_name for errors related to specific field. Like for error on username field, it will be form.errors.username
You HTML will look like
<div class='error'>{{form.errors.username}}</div>
<div class="form-label-group">
<input type="text" id="inputEmail" class="form-control" name="username" placeholder="Email address" required autofocus>
<label for="inputEmail">Email</label>
</div>

Django: Redirect Change Password URL

I have the following two URLs:
url(r'^change-password/$',django.contrib.auth.views.password_change,{'template_name': 'meta/changepassword.html', 'post_change_redirect': '/password-changed/'},name='change_password'),
url(r'^change-passwordiOS/$',django.contrib.auth.views.password_change,{'template_name': 'meta/changepassword.html', 'post_change_redirect': '/password-changed/'},name='change_passwordiOS'),
I thought if I used the following within the change password form it would override what URL would be loaded:
{% if 'iOS' in request.path %}
<input type="hidden" name="next" value="/profileiOS/" />
{% endif %}
But when I reach the change password from the url(r'^change-passwordiOS/$' and click the "Change Button" it does not goto the /profileiOS/ as expected but the standard /profile/ URL.
Any help would be appreciated.
/change-password/ view:
#login_required
def password_changed(request):
messages.success(request, 'Your password has been changed.')
return redirect(reverse('profile'))
Full Change Password Form:
<form class="form-horizontal" role="form" method="post" action="">
{% csrf_token %}
<fieldset>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.old_password.label }}:</label>
<div class="col-md-6">
<input name="old_password" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.old_password.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.new_password1.label }}:</label>
<div class="col-md-6">
<input name="new_password1" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.new_password1.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-6 control-label">{{ form.new_password2.label }}:</label>
<div class="col-md-6">
<input name="new_password2" type="password" class="form-control"/>
<div class="text-danger">
{% for error in form.new_password2.errors %}{{ error }}<br/>{% endfor %}
</div>
</div>
</div>
<div class="form-group">
<div class="text-right col-sm-12">
<button type="submit" class="btn btn-primary">Change Password^</button>
</div>
</div>
</fieldset>
{% if 'iOS' in request.path %}
<input type="hidden" name="next" value="/profileiOS/" />
{% endif %}
</form>
You are manually redirecting to /profile/ in password_changed view. You can change your redirect logic to depend on post param from template:
#login_required
def password_changed(request):
messages.success(request, 'Your password has been changed.')
return redirect(request.POST.get('next', reverse('profile')))