I have almost implemented the password reset process, but when I validate the password change I don't end up on the reset complete template and get the template says:
The password reset link was invalid...
However, the password change has been made and can log in with the new password. It looks the redirection is wrong but I can't figure out why.
Here is my urls.py:
path('reset/<uidb64>/<token>', auth_views.PasswordResetConfirmView.as_view(
template_name='news/user/password_reset_confirm.html',
success_url='../password-change/done'), name='password_reset_confirm'),
path('password-change/done', auth_views.PasswordResetCompleteView.as_view(template_name='news/user/password_reset_complete.html'), name='password_change_done'),
Here is my template:
{% block content %}
{% if validlink %}
<p>Please enter your new password twice so we can verify you typed it in correctly.</p>
<form method="post">{% csrf_token %}
<fieldset class="module aligned">
<div class="form-row field-password1">
{{ form.new_password1.errors }}
<label for="id_new_password1">New password:</label>
{{ form.new_password1 }}
</div>
<div class="form-row field-password2">
{{ form.new_password2.errors }}
<label for="id_new_password2">Confirm password:</label>
{{ form.new_password2 }}
</div>
<input type="submit" value="Change my password">
</fieldset>
</form>
{% else %}
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
{% endif %}
{% endblock %}
You're missing a final slash on the password_reset_confirm path, which is causing your POST to go to the wrong place. It should be:
path('reset/<uidb64>/<token>/', ...
Note that your success_url is also probably wrong, I doubt that .. will work the way you think it will.
Related
I am trying to create a login form in django that accepts either username or email. I made custom authentication backend and it does work. Problem is in HTML input type. The form method is POST and i did write csrf_token tag, but if i set input type to text, than when i try to login with username everything works, but when i put email in it, i get an error: CSRF verification failed. Request aborted. And if i set type to email, than i can't put username in. My django version is 4.0.6 and python version is 3.10.4
Add this in urls.py file
path('', include('django.contrib.auth.urls')),
Add this in your HTML template
{% extends 'registration/base.html' %}
{% block title %} Login {% endblock title %}
{% load crispy_forms_tags %}
{% block body %}
<h4>Hello! let's get started</h4>
<h6 class="font-weight-light">Sign in to continue.</h6>
<form class="pt-3" method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="mt-3">
<button class="btn btn-block btn-primary btn-lg font-weight-medium auth-form-btn">SIGN IN</button>
</div>
<div class="my-2 d-flex justify-content-between align-items-center">
<div class="form-check">
<label class="form-check-label text-muted">
<input type="checkbox" class="form-check-input"> Keep me signed in </label>
</div>
Forgot password?
</div>
<div class="text-center mt-4 font-weight-light">
</div>
</form>
I am using the django all-auth login form. I wanted to customize the look of the form fields so I changed login.html within the account folder to look like this:
<form class="login" method="POST" action="{% url 'account_login' %}">
{% csrf_token %}
{% for field in form.visible_fields|slice:'2' %}
<div class="row form-group">
{% if field.name == 'login' %}
<input type="text" placeholder="Email"><i class="fas fa-at"></i>
{% else %}
<input type="password" placeholder="Password"><i class="la la-lock"></i>
{% endif %}
</div>
{% endfor %}
Forgot Password?
<button type="submit">Sign In</button>
</form>
The form renders exactly how I would like it to, however nothing happens when I click on submit. What is strange to me is that the form submits perfectly fine if in place of my for loop I simply type {{ form.as_p }}, it just doesn't look how I want. Can anyone see an error in my loop, or is there something else wrong here. I have been looking for a solution online but so far been unsuccessful
You need to specify the names of the fields in your input tags otherwise the POST dictionary will be empty. You are using {% if field.name == 'login' %} but you forgot to specify the name attribute. Same applies for the password input.
<form class="login" method="POST" action="{% url 'account_login' %}">
{% csrf_token %}
{% for field in form.visible_fields|slice:'2' %}
<div class="row form-group">
{% if field.name == 'login' %}
<input name='login' type="text" placeholder="Email"><i class="fas fa-at"></i>
{% else %}
<input name='password' type="password" placeholder="Password"><i class="la la-lock"></i>
{% endif %}
</div>
{% endfor %}
Forgot Password?
<button type="submit">Sign In</button>
</form>
the link to password reset is not showing
console output of password reset
Hi there, Someone asked for a password reset for the email
address root#gmail.com, Follow the link below: http://127.0.0.1:8000 {% url
'password_reset_confirm' uidb64=uid token=token %}
HTML FILES
password_reset.html
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="send password reset email" name="submit" />
</form>
password_reset_email.html
Hi there, Someone asked for a password reset for the email
address {{ email }}, Follow the link below: {{ protocol }}://
{{ domain}} {% url'password_reset_confirm' uidb64=uid token=token %}
password_reset_confirm.html
<div>
{% if validlink %}
<h2>change password for 0{{ form.user.username }}</h2>
<form action="" method="POST" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="changepassword" name="submit" />
</form>
{% else %}
<h3>Reset your password</h3>
<p>it looks like you clicked on an invalid passowrd reset link try again</p>
Request
{% endif %}
</div>
settings.py
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
acoounts/urls.py
path("accounts/", include("django.contrib.auth.urls")),
Please check the following things.
{{ protocol }}://{{ domain}} {% url'password_reset_confirm' uidb64=uid token=token %}
Remove the space between {{ domain}} {% url''}
Check that your email template is getting value for protocol and domain
Inspect in the email and check what is the final link is.
I faced the same problem, all I had to do was put the code on the same line.
{{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %}
Make sure the code is not broken into a new line.
http://127.0.0.1:8000/accounts/password_reset/
Try this
you just have to add the URL which is link to login .
I am using django.auth.contrib as my session based authentication framework.
I have successfully implemented a reset password feature via PasswordResetConfirmView which requires a valid token sent to a user's email to set a new password.
path('password_reset/confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='accounts/password_reset/password_reset_confirm.html'),
name='password_reset_confirm'),
This works fine if the token is valid. However, if the token is not valid (e.g. incorrect or expired), then I predictably get an error:
Reverse for 'password_reset_confirm' with arguments '('', '')' not
found. 1 pattern(s) tried:
['accounts/password_reset/confirm/(?P[^/]+)/(?P[^/]+)/$']
What's the best practice to handle this exception for the user? Ideally I want to catch it and intercept it with "Sorry, your token is invalid." Is there an existing way to do this within the django.contrib.auth framework? Looking for the best DRY approach.
Edit I am already using the validlink context in the template. The error appears to be prior to this:
{% block content %}
<h1>{{ title }}</h1>
{% if validlink %}
<p>Please enter your new password twice so we can verify you typed it in correctly.</p>
<form method="post">{% csrf_token %}
<fieldset>
<div>
{{ form.new_password1.errors }}
<label for="id_new_password1">New password:</label>
{{ form.new_password1 }}
</div>
<div>
{{ form.new_password2.errors }}
<label for="id_new_password2">Confirm password:</label>
{{ form.new_password2 }}
</div>
<input type="submit" value="Change my password">
</fieldset>
</form>
{% else %}
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
{% endif %}
{% endblock %}
I know there are multiple questions like this around, but none of them contain a clear answer. I am using the default authentication from Django, but have trouble displaying something like 'Your username/password combination is incorrect'. Is it possible to fix this without making a custom view function?
My urls.py looks like this:
url(r'^login/$', auth_views.login, {'template_name': 'login.html'},
name='mysite_login')
Then my login.html has the following code:
{% block content %}
<section class="content">
<div class="container block">
<div class="row">
<div class="col-md-12"></div>
<form action="{% url 'mysite_login' %}" class="form-control" method="post" accept-charset="utf-8">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field|addcss:'form-control' }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text|safe }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit" class="btn btn-dark">Login</button>
<input class="form-control" type="hidden" name="next" value="{{ next }}"><br>
</form>
</div>
</div>
</div>
</section>
{% endblock %}
So this all works, except for displaying the error messages. I've seen answers where you can write a custom view function and form to fix this, but I assume it should be also possible while using the build-in login functionality right? Thanks a lot.
The built-in login form doesn't display errors at an individual field level; it's a security risk to say that just the password is wrong, because it confirms the existence of a particular username. So the errors are raised in the general clean() method and are displayed in the template via {{ form.non_field_errors }}.