How to use the built-in 'password_reset' view in Django? - python

I have set the following entry in the urls.py
(r'^password_reset/$', 'django.contrib.auth.views.password_reset'),
but once I go to http://127.0.0.1:8000/password_reset/ I get the error message:
NoReverseMatch at /password_reset/
Reverse for 'django.contrib.auth.views.password_reset_done' with arguments '()' and keyword arguments '{}' not found.
I was expecting password_reset_done view also to be coming out of the box. So what am I supposed to do at this stage?
UPDATE
After trying Blair's solution, I got a step closer.
(r'^password_reset_done/$', 'django.contrib.auth.views.password_reset_done'),
According to the book 'Django 1.0 Website Development', these built-in views should be used out of the box without further hassle. But maybe it has changed since Django 1.0...
Would be great if someone could shed light on this. Thanks

I have finally found the solution. I think there is always the slight misunderstanding between MVC and MTV pattern. In MTV (Django) the View stands for the controller and the Template stands for the View.
Hence while its true that the change password "Views" are coming built-in out-of-the-box, the actual templates (look & feel) still needs to be generated by the user while the underlying form (widget) is generated by Django automatically. It gets more clear when looking at the code.
Therefore add these two lines to url.py
(r'^change-password/$', 'django.contrib.auth.views.password_change'),
(r'^password-changed/$', 'django.contrib.auth.views.password_change_done'),
Then Under myproject/templates/registration add these two files
password_change_done.html
{% extends "base.html" %}
{% block title %}Password Change Successful{% endblock %}
{% block head %}Password Change Completed Successfully{% endblock %}
{% block content %}
Your password has been changed successfully. Please re-login with your new credentials
login or go back to the
main page.
{% endblock %}
password_change_form.html
{% extends "base.html" %}
{% block title %}Change Registration{% endblock %}
{% block head %}Change Registration{% endblock %}
{% block content %}
<form method="post" action=".">
{{form.as_p}}
<input type="submit" value="Change" />
{% csrf_token %}
</form>
{% endblock %}

Django needs to know which URL to redirect the user to once they have completed the form on the password_reset page. So add another line to your URL configuration:
(r'^password_reset_done/$', 'django.contrib.auth.views.password_reset_done'),

As of django 1.11 password_change view is deprecated.
Deprecated since version 1.11: The password_change function-based view should be replaced by the class-based PasswordChangeView.
What worked for me was:
In urls.py
from django.contrib.auth import views as auth_views
...
url('^account/change-password/$',
auth_views.PasswordChangeView.as_view(
template_name='registration/passwd_change_form.html'),
name='password_change'),
url(r'^account/password-change-done/$',
auth_views.PasswordChangeDoneView.as_view(
template_name='registration/passwd_change_done.html'),
name='password_change_done'),
And then add the couple of templates passwd_change_form.html and passwd_change_done.html under registration.
Note that I'm not using the default name, for some reason when I did that it defaulted to the django admin views.

Related

Unable to change Django default templates

I'm learning Django using W. Vincent's "Django for beginners". I got to the part where we have to customize the password change page (p. 186). According to the author:
"Django already has created the views and URLs for us, we only need to
change the templates."
I created a new template password_change_form.html but when I start a local server and go to the localhost/accounts/password_change, I still see the old default page with the "Django Administration" header. Here is the code:
{% extends "base.html" %}
{% block title %}Password Change{% endblock title %}
{% block content %}
<h1>Password change</h1>
<p>Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly.</p>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input class="btn btn-success" type="submit" value="Change my password">
</form>
{% endblock content %}
I'm surprised because everything worked well up until this point, as I was able to successfully updated the login and signup pages' templates. What do you think might be going wrong? Thanks.
This is happening because in "Django For Beginners" book, the author does not configure static file setting in the settings.py file the css you are seeing in the template is because of bootstrap's cdn.
If you want to clear that problem you have to configure static files settings in settings.py.
This article by the same author can be helpful for you

Implementing Django Bootstrap crispy forms into default signup / login pages?

I've set up user account signup and login pages following this tutorial and it all works great, except the pages have no formatting. I'm now looking for a simple drop in solution to improve the appearance of "templates/registration/login.html" and "templates/registration/signup.html". Someone recommended crispy forms which look great, and as the rest of my site uses Bootstrap 5, crispy-bootstrap5 looks ideal.
I'm struggling to implement crispy-bootstrap5 as I don't understand Django's inbuilt django.contrib.auth.forms nor forms in general, and can't find simple reproducible examples for crispy forms with signup.html and login.html. I've installed packages fine, but now don't know how to beautify login.html and signup.html from that tutorial:
{% extends 'base.html' %}
{% block title %}Sign Up{% endblock %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
{% endblock %}
I don't know where to go with this, but the docs for regular django-crispy links to a gist for an eg form, and the index.html {% load crispy_forms_tags %} and {% crispy form %}. I've put them in which mostly left the page unchanged except for messing up the formatting. I think I now need to modify class CustomUserCreationForm(UserCreationForm) in forms.py but I don't know how. I'm also reluctant to risk bigger problems by modifying Django's inbuilt functionalities I don't understand.
What steps need we take to get login.html and signup.html looking like bootstrap 5?
please follow bellow steps to use crispy_forms with bootstrap5:
1st step: Install crispy_forms form bootstrap 5
pip install crispy-bootstrap5
step 2: Add crispy_forms and crispy_bootstrap5 to installed apps
INSTALLED_APPS = (
...
"crispy_forms",
"crispy_bootstrap5",
...
)
step 3: add crispy form attr to settings file
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
check here for details
to use crispy form in templates, add {% load crispy_forms_filters %} and {% load crispy_forms_tags %} on top of your sign up and login page.
and declare form as crispy i.e {{forms| crispy}} or field as {{ form.fieldname|as_crispy_field }}

Django: Extending base.html in django admin

I've a base.html file which has vertical and horizontal menu-bar:
Wherever I want to use that I just simply write:
{% extends 'base.html' %}
{% block content %}
//html code
{% endblock content %}
But I don't know how to use the same file base.html from templates directory in djando admin.
I want output like this:
What I Tried:
How to override and extend basic Django admin templates?
How do I correctly extend the django admin/base.html template?
Override Navbar in Django base admin page to be same as the base.html
I tried few other solution just don't want to increase the length of question and base.html file's code just has basic bootstrap, html code for menus.
I am new to Django, little explanation would be highly appreciated!
What you are looking is similar to nav-global.
Try this:
First create a folder in your templates folder as admin and create a html file(base_site.html) in the same folder
Assuming you have separate html file for menu-bars(Let's say the file is nav.html).
Write the below code in base_site.html:
{% extends 'admin/base.html' %}
{% block nav-global %}
{% include 'nav.html' %} #Your navigation html file
{% endblock %}
Unrelated to question: I found a git repo which will give you idea how to customize the django-admin menu.
You can just extend the admin's base template as
{% extends "admin/base.html" %}
For example:
{% extends "admin/base.html" %}
{% block sidebar %}
{{ block.super }}
<div>
<h1>Extra links</h1>
My extra link
</div>
{% endblock %}
Also, make sure that you have added the admin app to the INSTALLED_APPS
INSTALLED_APPS = [
# other apps,
'django.contrib.admin',
# other apps,
]
I had the same issue about a year and a half ago and I found a nice template loader on djangosnippets.org that makes this easy. It allows you to extend a template in a specific app, giving you the ability to create your own admin/index.html that extends the admin/index.html template from the admin app. Like this:
{% extends "admin:admin/index.html" %}
{% block sidebar %}
{{block.super}}
<div>
<h1>Extra links</h1>
My extra link
</div>
{% endblock %}

Catching TemplateDoesNotExist in Django

I am trying to use the templatetag described in SO answer: https://stackoverflow.com/a/6217194/493211 in a project using Django 1.4.3 (with Python 2.7.2).
I adapted it like this:
from django import template
register = template.Library()
#register.filter
def template_exists(template_name):
try:
template.loader.get_template(template_name)
return True
except template.TemplateDoesNotExist:
return False
So that I could use it like this in another template:
{% if 'profile/header.html'|template_exists %}
{% include 'profile/header.html' %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
This way, I could have avoided using solutions such as changing the order of my apps in INSTALLED_APPS.
However, it does not work. If the template does not exist, then the exception is raised within the stack/console but it is not propagated up to get_template(..) (from inside this statement), and thus not to my foolish API. Hence, this blows up in my face during the rendering. I uploaded the stacktrace to pastebin
Is this a wanted behavior from Django?
I ended up stop doing foolish things as is. But my question would remain.
What about a custom tag? This doesn't provide the full functionality of include but seems to meet the needs in the question.:
#register.simple_tag(takes_context=True)
def include_fallback(context, *template_choices):
t = django.template.loader.select_template(template_choices)
return t.render(context)
Then in your template:
{% include_fallback "profile/header.html" "common/header.html" %}
I found some kind of an answer to my question so I am posting it here for future refence.
If I use my template_exists filter like this
{% if 'profile/header.html'|template_exists %}
{% include 'profile/header.html' %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
and if profile/header.html does not exist, then the TemplateDoesNotExist gets strangely propagated at page load and I get a server error. However, if instead, I use this in my template:
{% with 'profile/header.html' as var_templ %}
{% if var_templ|template_exists %}
{% include var_templ %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
{% endwith %}
Then, it works like a charm!
Obviously, I could have used
django.template.loader.select_template(['profile/header.html','common/header.html'])
in the view (from this SO answer). But I am using a CBV which I wanted to keep rather generic and this was called from the main template. And also I thought it would be nice to have my site working if this apps goes down for whatever reason. If this seems silly to you, please leave a comment (or yet a better answer).

Django 1.0, using default password reset

I'm trying to use the password reset setup that comes with Django, but the documentation is not very good for it. I'm using Django 1.0 and I keep getting this error:
Caught an exception while rendering: Reverse for 'mysite.django.contrib.auth.views.password_reset_confirm' with arguments '()' and keyword arguments ...
in my urlconf I have something like this:
#django.contrib.auth.views
urlpatterns = patterns('django.contrib.auth.views',
(r'^password_reset/$', 'password_reset', {'template_name': 'accounts/registration/password_reset_form.html', 'email_template_name':'accounts/registration/password_reset_email.html', 'post_reset_redirect':'accounts/login/'}),
(r'^password_reset/done/$', 'password_reset_done', {'template_name': 'accounts/registration/password_reset_done.html'}),
(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 'password_reset_confirm', {'template_name': 'accounts/registration/password_reset_confirm.html', 'post_reset_redirect':'accounts/login/', 'post_reset_redirect':'accounts/reset/done/'}),
(r'^reset/done/$', 'password_reset_complete', {'template_name': 'accounts/registration/password_reset_complete.html'}),
)
The problem seems to be in this file:
password_reset_email.html
on line 7
{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %}
I'm at loss as to what's going on, so any help would be appreciated.
Thanks
Edit: I used your example, and had to change to not use keyword parameters.
{% url django.contrib.auth.views.password_reset_confirm uid, token %}
Named parameters do work, as long as both uid and token are defined. If either are not defined or blank I get the same error you do:
{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %}
Just wanted to post the solution I came up with. The problem was in this line:
{% url django.contrib.auth.views.password_reset_confirm uidb36=uid, token=token %}
I'm not really a 100% why either, so I just hard coded the url like this:
http://mysite.com/accounts/reset/{{uid}}-{{token}}/
I've struggled with this for over an hour trying everything on this page and every other page on the internet. Finally to solve the problem in my case i had to delete
{% load url from future %}
from the top of my password_reset_email.html template.
Also note, "uidb36=uid" in the url script. Here's my full password_reset_email.html template, I hope it saves someone some time:
{% autoescape off %}
You're receiving this e-mail because you requested a password reset for your user account at {{ site_name }}.
Please go to the following page and choose a new password:
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url django.contrib.auth.views.password_reset_confirm uidb36=uid token=token %}
{% endblock %}
Your username, in case you've forgotten:" %} {{ user.username }}
Thanks for using our site!
The {{ site_name }} team
{% endautoescape %}
This is a problem I figured out myself not 10 minutes ago. The solution is to add the post_change_redirect value to the dictionary of arguments you are passing to the password_reset view.
So this is what mine now look like:
(r'^/password/$', password_change, {'template_name': 'testing/password.html', 'post_change_redirect': '/account/'})
I hope that does it for you! I agree that the documentation for this particular feature is lacking somewhat, but this solved the exact same issue for my project.
Edit: I really should have scrolled across - you've included that already. Apologies for that, but I hope you get it sorted :)

Categories

Resources