How do I use the built in password reset/change views with my own templates

123,440

Solution 1

If you take a look at the sources for django.contrib.auth.views.password_reset you'll see that it uses RequestContext. The upshot is, you can use Context Processors to modify the context which may allow you to inject the information that you need.

The b-list has a good introduction to context processors.

Edit (I seem to have been confused about what the actual question was):

You'll notice that password_reset takes a named parameter called template_name:

def password_reset(request, is_admin_site=False, 
            template_name='registration/password_reset_form.html',
            email_template_name='registration/password_reset_email.html',
            password_reset_form=PasswordResetForm, 
            token_generator=default_token_generator,
            post_reset_redirect=None):

Check password_reset for more information.

... thus, with a urls.py like:

from django.conf.urls.defaults import *
from django.contrib.auth.views import password_reset

urlpatterns = patterns('',
     (r'^/accounts/password/reset/$', password_reset, {'template_name': 'my_templates/password_reset.html'}),
     ...
)

django.contrib.auth.views.password_reset will be called for URLs matching '/accounts/password/reset' with the keyword argument template_name = 'my_templates/password_reset.html'.

Otherwise, you don't need to provide any context as the password_reset view takes care of itself. If you want to see what context you have available, you can trigger a TemplateSyntax error and look through the stack trace find the frame with a local variable named context. If you want to modify the context then what I said above about context processors is probably the way to go.

In summary: what do you need to do to use your own template? Provide a template_name keyword argument to the view when it is called. You can supply keyword arguments to views by including a dictionary as the third member of a URL pattern tuple.

Solution 2

Strongly recommend this article.

I just plugged it in and it worked

http://garmoncheg.blogspot.com.au/2012/07/django-resetting-passwords-with.html

Solution 3

You just need to wrap the existing functions and pass in the template you want. For example:

from django.contrib.auth.views import password_reset

def my_password_reset(request, template_name='path/to/my/template'):
    return password_reset(request, template_name)

To see this just have a look at the function declartion of the built in views:

http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/views.py#L74

Solution 4

You can do the following:

  1. add to your urlpatterns (r'^/accounts/password/reset/$', password_reset)
  2. put your template in '/templates/registration/password_reset_form.html'
  3. make your app come before 'django.contrib.auth' in INSTALLED_APPS

Explanation:

When the templates are loaded, they are searched in your INSTALLED_APPS variable in settings.py . The order is dictated by the definition's rank in INSTALLED_APPS, so since your app come before 'django.contrib.auth' your template were loaded (reference: https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loaders.app_directories.Loader).

Motivation of approach:

  1. I want be more dry and don't repeat for any view(defined by django) the template name (they are already defined in django)
  2. I want a smallest url.py

Solution 5

Another, perhaps simpler, solution is to add your override template directory to the DIRS entry of the TEMPLATES setting in settings.py. (I think this setting is new in Django 1.8. It may have been called TEMPLATE_DIRS in previous Django versions.)

Like so:

TEMPLATES = [
   {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # allow overriding templates from other installed apps                                                                                                
        'DIRS': ['my_app/templates'],
        'APP_DIRS': True,
}]

Then put your override template files under my_app/templates. So the overridden password reset template would be my_app/templates/registration/password_reset_form.html

Share:
123,440
Tom Viner
Author by

Tom Viner

Updated on March 03, 2020

Comments

  • Tom Viner
    Tom Viner about 4 years

    For example I can point the url '^/accounts/password/reset/$' to django.contrib.auth.views.password_reset with my template filename in the context but I think need to send more context details.

    I need to know exactly what context to add for each of the password reset and change views.

  • jb.
    jb. over 15 years
    I believe the question is about using different templates with builtin views - Context processors doesn't factor into it!
  • jb.
    jb. over 15 years
    The documentation says there is an "optional argument" called "template_name" which seems more relevant.
  • user1066101
    user1066101 over 15 years
    The optional argument is an argument to the function, not context provided to the form.
  • jb.
    jb. over 15 years
    Mmm- I think the question is confusing in that it talks about 'context' when really all that's relevant to solving this is the arguments of the password_reset view.
  • mabdrabo
    mabdrabo about 11 years
    any idea, how to let registration/password_reset_email.html actually contain html elements like: <div>, <a> because this sends text only
  • dougvk
    dougvk over 10 years
    great link, thanks. for those following the link - django-registration now includes the default auth views...so all you have to do is create the templates detailed in the above link. also - use django-crispy-forms if you want to avoid all the manual html form work he did as well.
  • gregoltsov
    gregoltsov over 10 years
    @mabdrabo - check out this article on how to get HTML working.
  • Matt Vukas
    Matt Vukas over 10 years
    There's some legacy Django code I have to manage at work, but I barely know anything about the framework. That guy saved my ass! Great tutorial
  • ihatecache
    ihatecache over 8 years
    Thanks for the link! I think this should be the accepted answer since like you said, plugged it in and it worked.