When using Django3.0 internal PasswordResetConfirmView
PasswordResetForm
reset_password.html
and tampering with the token generated it raises a form "is_bound"
error. It doesn't redirect to some failure url.
Internal Server Error: /account/password/reset/MQ/akbdyj-e5f18868fas35e748160dd6ef006803a5/
Traceback (most recent call last):
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\core\handlers\base.py", line 204, in _get_response
response = response.render()
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\response.py", line 108, in render
self.content = self.rendered_content
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\response.py", line 86, in rendered_content
return template.render(context, self._request)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\backends\django.py", line 61, in render
return self.template.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 170, in render
return self._render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 162, in _render
return self.nodelist.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 938, in render
bit = node.render_annotated(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 905, in render_annotated
return self.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\loader_tags.py", line 150, in render
return compiled_parent._render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 162, in _render
return self.nodelist.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 938, in render
bit = node.render_annotated(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 905, in render_annotated
return self.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\loader_tags.py", line 62, in render
result = block.nodelist.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 938, in render
bit = node.render_annotated(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\django\template\base.py", line 905, in render_annotated
return self.render(context)
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\crispy_forms\templatetags\crispy_forms_tags.py", line 203, in render
c = self.get_render(context).flatten()
File "C:\Users\JoyStick\.virtualenvs\django-template-2StZ7f6a\lib\site-packages\crispy_forms\templatetags\crispy_forms_tags.py", line 112, in get_render
node_context.update({"is_bound": actual_form.is_bound})
AttributeError: 'NoneType' object has no attribute 'is_bound'
I have tried passing the failure template name in "extra_context" but still, it doesn't work.
class UserAccountResetPasswordView(PasswordResetConfirmView):
template_name = 'user_account/profile/reset_password.html'
form_class = UserAccountPasswordResetForm
success_url = reverse_lazy('user_account:login')
extra_context = {
'template_name': 'user_account/profile/reset_password_failed.html'
}
Form
class UserAccountPasswordResetForm(SetPasswordForm):
new_password1 = forms.CharField(
label=_("New password"),
strip=False,
widget=forms.PasswordInput(
attrs={
'class': 'form-control',
'id': 'toggle-password-type',
'placeholder': 'New Password'
}),
)
new_password2 = forms.CharField(
label=_("Confirm new password"),
strip=False,
widget=forms.PasswordInput(
attrs={
'class': 'form-control',
'placeholder': 'Confirm New Password'
}),
)
class Meta:
fields = ['new_password1', 'new_password2']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_show_labels = False
self.helper.form_tag = False
self.helper.layout = Layout(
Field(AppendedText('new_password1',
'<i onclick="passwordTypeToggle()" class="fa fa-eye"></i>')),
'new_password2',
)
def clean_new_password1(self):
new_password1 = self.cleaned_data.get("new_password1")
if not re.search(
"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)[A-Za-z\d@!#$%&*()_+-= ]{8,}$",
new_password1
):
raise ValidationError(
'Password should have 8 to 15 characters which contain only characters, numeric digits, underscore and first character must be a letter', code='signup'
)
return new_password1
reset_password.html
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content" id="container-fluid">
<div class="card shadow-sm rounded" style="max-width: 500px; margin: auto;">
<div class="card-body">
<h1>Reset Password</h1>
<hr>
<form method="post">
{% crispy form %}
<div class="row">
<div class="col-12 text-right">
<button type="submit" class="btn btn-primary">Confirm</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock content %}
Passing a template name in extra_context
does nothing. If the token is not valid the PasswordResetConfirmView
sets the form
to None
and passes it to the context. You try to render that form getting an error. Instead you should check the variable validlink
passed in the context to indicate that the link is correct or not and render appropriately:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
{% if validlink %}
<div class="content" id="container-fluid">
<div class="card shadow-sm rounded" style="max-width: 500px; margin: auto;">
<div class="card-body">
<h1>Reset Password</h1>
<hr>
<form method="post">
{% crispy form %}
<div class="row">
<div class="col-12 text-right">
<button type="submit" class="btn btn-primary">Confirm</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% else %}
<!--Render here as per your preferences to indicate the link is invalid-->
Looks like you clicked on an invalid password reset link. Please try again.
{% endif %}
{% endblock content %}