Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save amccloud/2201802 to your computer and use it in GitHub Desktop.
Save amccloud/2201802 to your computer and use it in GitHub Desktop.

Revisions

  1. @bmispelon bmispelon revised this gist Feb 18, 2012. 1 changed file with 183 additions and 206 deletions.
    389 changes: 183 additions & 206 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -2,9 +2,8 @@
    import urlparse

    from django.conf import settings
    from django.core.urlresolvers import reverse, reverse_lazy
    from django.core.urlresolvers import reverse_lazy
    from django.http import HttpResponseRedirect, QueryDict
    from django.template.response import TemplateResponse
    from django.utils.decorators import method_decorator
    from django.utils.http import base36_to_int
    from django.utils.translation import ugettext as _
    @@ -55,7 +54,7 @@ def get_default_redirect_to(self):

    def get_success_url(self):
    default = self.get_default_redirect_to()
    redirect_to = self.request.REQUEST.get(self.get_redirect_field_name(), '')
    redirect_to = self.request.REQUEST.get(self.get_redirect_field_name())
    return redirect_to or default


    @@ -127,7 +126,7 @@ class LogoutView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.TemplateV
    """
    Logs out the user and displays 'You are logged out' message.
    """
    template_name='registration/logged_out.html'
    template_name = 'registration/logged_out.html'

    current_app = None
    extra_context = None
    @@ -155,7 +154,7 @@ def get(self, request, *args, **kwargs):
    # Render the template
    return super(LogoutView, self).get(request, *args, **kwargs)

    # TODO: define post(), put(), ... ?
    # XXX: define post(), put(), ... ?


    class LogoutThenLoginView(LogoutView):
    @@ -169,87 +168,6 @@ def next_page(self):
    return self.login_url or settings.LOGIN_URL


    def login(request, template_name=None, redirect_field_name=None,
    authentication_form=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for login -> LoginView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    kwargs["redirect_field_name"] = redirect_field_name
    if authentication_form is not None:
    kwargs["form_class"] = authentication_form
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    view = LoginView.as_view(**kwargs)
    return view(request)

    def logout(request, next_page=None, template_name=None,
    redirect_field_name=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for logout -> LogoutView
    """
    kwargs = {}

    if next_page is not None:
    kwargs["default_redirect_to"] = next_page
    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    kwargs["redirect_field_name"] = redirect_field_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    view = LogoutView.as_view(**kwargs)
    return view(request)

    def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for logout -> LogoutView
    """
    kwargs = {}

    if next_page is not None:
    kwargs["login_url"] = login_url
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context
    view = LogoutThenLoginView.as_view(**kwargs)
    return view(request)

    def redirect_to_login(next, login_url=None,
    redirect_field_name=REDIRECT_FIELD_NAME):
    """
    Redirects the user to the login page, passing the given 'next' page
    """
    if not login_url:
    login_url = settings.LOGIN_URL

    login_url_parts = list(urlparse.urlparse(login_url))
    if redirect_field_name:
    querystring = QueryDict(login_url_parts[4], mutable=True)
    querystring[redirect_field_name] = next
    login_url_parts[4] = querystring.urlencode(safe='/')

    return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))

    # 4 views for password reset:
    # - password_reset sends the mail
    # - password_reset_done shows a success message for the above
    # - password_reset_confirm checks the link the user clicked and
    # prompts for a new password
    # - password_reset_complete shows a success message for the above


    class PasswordResetView(CurrentAppMixin, generic.FormView):
    """
    Ask for the user's email address and send a message containing a token
    @@ -259,7 +177,7 @@ class PasswordResetView(CurrentAppMixin, generic.FormView):
    form_class = PasswordResetForm
    success_url = reverse_lazy('django.contrib.auth.views.password_reset_done')

    is_admin_site=False
    is_admin_site = False
    email_template_name = "registration/password_reset_email.html"
    subject_template_name = "registration/password_reset_subject.txt"
    token_generator = default_token_generator
    @@ -290,37 +208,6 @@ def get_context_data(self, **kwargs):
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordResetView, self).dispatch(request, *args, **kwargs)

    def password_reset(request, is_admin_site=None, template_name=None,
    email_template_name=None, subject_template_name=None,
    password_reset_form=None, token_generator=None,
    post_reset_redirect=None, from_email=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset -> PassworResetView
    """
    kwargs = {}

    if is_admin_site is not None:
    kwargs["is_admin_site"] = is_admin_site
    if template_name is not None:
    kwargs["template_name"] = template_name
    if email_template_name is not None:
    kwargs["email_template_name"] = email_template_name
    if password_reset_form is not None:
    kwargs["form_class"] = password_reset_form
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if from_email is not None:
    kwargs["from_email"] = from_email
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset = PasswordResetView.as_view(**kwargs)
    return password_reset(request)

    class PasswordResetDoneView(CurrentAppMixin, generic.TemplateView):
    """
    @@ -332,24 +219,8 @@ class PasswordResetDoneView(CurrentAppMixin, generic.TemplateView):
    extra_context = None

    def get_context_data(self):
    return self.extra_context # TODO: does this work?

    def password_reset_done(request, template_name=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_done -> PassworResetDoneView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_done = PasswordResetDoneView.as_view(**kwargs)
    return password_reset_done(request)
    # XXX: does this work?
    return self.extra_context


    class PasswordResetConfirmView(CurrentAppMixin, generic.UpdateView):
    @@ -403,33 +274,6 @@ def get_context_data(self, **kwargs):
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordResetConfirmView, self).dispatch(request, *args, **kwargs)

    def password_reset_confirm(request, uidb36=None, token=None,
    template_name=None, token_generator=None,
    set_password_form=None, post_reset_redirect=None,
    current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_confirm -> PassworResetConfirmView
    """
    assert uidb36 is not None and token is not None # checked by URLconf

    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if set_password_form is not None:
    kwargs["form_class"] = set_password_form
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_confirm = PasswordResetConfirmView.as_view(**kwargs)
    return password_reset_confirm(request, uidb36=uidb36, token=token)


    class PasswordResetComplete(CurrentAppMixin, generic.TemplateView):
    """
    @@ -447,24 +291,6 @@ def get_context_data(self, **kwargs):
    return context


    def password_reset_complete(request, template_name=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_complete -> PasswordResetComplete
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_complete = PasswordResetComplete.as_view(**kwargs)
    return password_reset_complete(request)


    class PasswordChangeView(CurrentAppMixin, generic.UpdateView):
    """
    Prompt the logged-in user for their old password and a new one and change
    @@ -492,28 +318,6 @@ def get_form_kwargs(self):
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordChangeView, self).dispatch(request, *args, **kwargs)

    def password_change(request, template_name=None, post_change_redirect=None,
    password_change_form=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_change -> PasswordChangeView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if post_change_redirect is not None:
    kwargs["success_url"] = post_change_redirect
    if password_change_form is not None:
    kwargs["form_class"] = password_change_form
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_change = PasswordChangeView.as_view(**kwargs)
    return password_change(request)


    class PasswordChangeDoneView(CurrentAppMixin, generic.TemplateView):
    """
    @@ -533,12 +337,185 @@ def get_context_data(self, **kwargs):
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordChangeDoneView, self).dispatch(request, *args, **kwargs)


    # Backwards-compatible stubs that call the class-based views:
    # login
    # logout
    # logout_then_login
    # redirect_to_login (not actually a view)
    # password_reset
    # password_reset_done
    # password_reset_confirm
    # password_reset_complete
    # password_change
    # password_change_done

    def login(request, template_name=None, redirect_field_name=None,
    authentication_form=None, current_app=None, extra_context=None):
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    kwargs["redirect_field_name"] = redirect_field_name
    if authentication_form is not None:
    kwargs["form_class"] = authentication_form
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    view = LoginView.as_view(**kwargs)
    return view(request)

    def logout(request, next_page=None, template_name=None,
    redirect_field_name=None, current_app=None, extra_context=None):
    kwargs = {}

    if next_page is not None:
    kwargs["default_redirect_to"] = next_page
    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    kwargs["redirect_field_name"] = redirect_field_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    view = LogoutView.as_view(**kwargs)
    return view(request)

    def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
    kwargs = {}

    if login_url is not None:
    kwargs["login_url"] = login_url
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context
    view = LogoutThenLoginView.as_view(**kwargs)
    return view(request)

    def redirect_to_login(next, login_url=None,
    redirect_field_name=REDIRECT_FIELD_NAME):
    """
    Redirects the user to the login page, passing the given 'next' page
    """
    if not login_url:
    login_url = settings.LOGIN_URL

    login_url_parts = list(urlparse.urlparse(login_url))
    if redirect_field_name:
    querystring = QueryDict(login_url_parts[4], mutable=True)
    querystring[redirect_field_name] = next
    login_url_parts[4] = querystring.urlencode(safe='/')

    return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))

    def password_reset(request, is_admin_site=None, template_name=None,
    email_template_name=None, subject_template_name=None,
    password_reset_form=None, token_generator=None,
    post_reset_redirect=None, from_email=None, current_app=None,
    extra_context=None):
    kwargs = {}

    if is_admin_site is not None:
    kwargs["is_admin_site"] = is_admin_site
    if template_name is not None:
    kwargs["template_name"] = template_name
    if email_template_name is not None:
    kwargs["email_template_name"] = email_template_name
    if password_reset_form is not None:
    kwargs["form_class"] = password_reset_form
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if from_email is not None:
    kwargs["from_email"] = from_email
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset = PasswordResetView.as_view(**kwargs)
    return password_reset(request)

    def password_reset_done(request, template_name=None, current_app=None,
    extra_context=None):
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_done = PasswordResetDoneView.as_view(**kwargs)
    return password_reset_done(request)

    def password_reset_confirm(request, uidb36=None, token=None,
    template_name=None, token_generator=None,
    set_password_form=None, post_reset_redirect=None,
    current_app=None, extra_context=None):
    assert uidb36 is not None and token is not None # checked by URLconf
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if set_password_form is not None:
    kwargs["form_class"] = set_password_form
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_confirm = PasswordResetConfirmView.as_view(**kwargs)
    return password_reset_confirm(request, uidb36=uidb36, token=token)

    def password_reset_complete(request, template_name=None, current_app=None,
    extra_context=None):
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_complete = PasswordResetComplete.as_view(**kwargs)
    return password_reset_complete(request)

    def password_change(request, template_name=None, post_change_redirect=None,
    password_change_form=None, current_app=None,
    extra_context=None):
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if post_change_redirect is not None:
    kwargs["success_url"] = post_change_redirect
    if password_change_form is not None:
    kwargs["form_class"] = password_change_form
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_change = PasswordChangeView.as_view(**kwargs)
    return password_change(request)

    def password_change_done(request, template_name=None, post_change_redirect=None,
    password_change_form=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_change_done -> PasswordChangeDoneView
    """
    kwargs = {}

    if template_name is not None:
  2. @bmispelon bmispelon revised this gist Feb 18, 2012. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,7 @@ class RedirectToMixin(object):
    """
    redirect_field_name = REDIRECT_FIELD_NAME
    default_redirect_to = None

    def get_redirect_field_name(self):
    return self.redirect_field_name

    @@ -86,7 +86,7 @@ class LoginView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.FormView):

    current_app = None
    extra_context = None

    default_redirect_to = settings.LOGIN_REDIRECT_URL

    @method_decorator(sensitive_post_parameters())
    @@ -131,7 +131,7 @@ class LogoutView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.TemplateV

    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(LogoutView, self).get_context_data(**kwargs)
    current_site = get_current_site(self.request)
    @@ -151,7 +151,7 @@ def get(self, request, *args, **kwargs):
    # Redirect to the current page if no default has been provided
    redirect_to = redirect_to or self.request.path
    return HttpResponseRedirect(redirect_to)

    # Render the template
    return super(LogoutView, self).get(request, *args, **kwargs)

    @@ -163,7 +163,7 @@ class LogoutThenLoginView(LogoutView):
    Logs out the user if he is logged in. Then redirects to the log-in page.
    """
    login_url = None

    @property
    def next_page(self):
    return self.login_url or settings.LOGIN_URL
    @@ -280,7 +280,7 @@ def form_valid(self, form):
    opts['domain_override'] = self.request.META['HTTP_HOST']
    form.save(**opts)
    return super(PasswordResetView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    context = super(PasswordResetView, self).get_context_data(**kwargs)
    context.update(self.extra_context or {})
  3. @bmispelon bmispelon revised this gist Feb 18, 2012. 1 changed file with 31 additions and 20 deletions.
    51 changes: 31 additions & 20 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -2,15 +2,16 @@
    import urlparse

    from django.conf import settings
    from django.core.urlresolvers import reverse
    from django.core.urlresolvers import reverse, reverse_lazy
    from django.http import HttpResponseRedirect, QueryDict
    from django.template.response import TemplateResponse
    from django.utils.decorators import method_decorator
    from django.utils.http import base36_to_int
    from django.utils.translation import ugettext as _
    from django.views import generic
    from django.views.decorators.debug import sensitive_post_parameters
    from django.views.decorators.cache import never_cache
    from django.views.decorators.csrf import csrf_protect
    from django.views import generic

    # Avoid shadowing the login() and logout() views below.
    from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout
    @@ -32,7 +33,7 @@ def render_to_response(self, context, **response_kwargs):
    request=self.request,
    template=self.get_template_names(),
    context=context,
    current_app=self.current_app.
    current_app=self.current_app,
    **response_kwargs
    )

    @@ -64,11 +65,15 @@ class ProtectectedRedirectToMixin(RedirectToMixin):
    """
    def get_success_url(self):
    redirect_to = super(ProtectectedRedirectToMixin, self).get_success_url()

    if not redirect_to:
    return redirect_to

    netloc = urlparse.urlparse(redirect_to)[1]

    if not netloc or netloc == self.request.get_host():
    return redirect_to

    return self.get_default_redirect_to()


    @@ -105,19 +110,17 @@ def form_valid(self, form):
    return super(LoginView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    ctx = super(LoginView, self).get_context_data(**kwargs)

    context = super(LoginView, self).get_context_data(**kwargs)
    current_site = get_current_site(self.request)

    ctx.update({
    context.update({
    self.get_redirect_field_name(): self.get_success_url(),
    "site": current_site,
    "site_name": current_site.name,
    })

    ctx.update(self.extra_context or {})
    context.update(self.extra_context or {})

    return ctx
    return context


    class LogoutView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.TemplateView):
    @@ -131,6 +134,7 @@ class LogoutView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.TemplateV

    def get_context_data(self, **kwargs):
    context = super(LogoutView, self).get_context_data(**kwargs)
    current_site = get_current_site(self.request)
    context.update({
    'site': current_site,
    'site_name': current_site.name,
    @@ -139,12 +143,19 @@ def get_context_data(self, **kwargs):
    context.update(self.extra_context or {})
    return context

    def get_default_redirect_to(self):
    return self.default_redirect_to or self.request.path

    def dispatch(self, request, *args, **kwargs): # TODO: GET, POST, ... ?
    def get(self, request, *args, **kwargs):
    auth_logout(request)
    return HttpResponseRedirect(self.get_success_url())
    redirect_to = self.get_success_url()

    if redirect_to is not None:
    # Redirect to the current page if no default has been provided
    redirect_to = redirect_to or self.request.path
    return HttpResponseRedirect(redirect_to)

    # Render the template
    return super(LogoutView, self).get(request, *args, **kwargs)

    # TODO: define post(), put(), ... ?


    class LogoutThenLoginView(LogoutView):
    @@ -197,7 +208,7 @@ def logout(request, next_page=None, template_name=None,
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    view = Logout.as_view(**kwargs)
    view = LogoutView.as_view(**kwargs)
    return view(request)

    def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
    @@ -265,7 +276,7 @@ def form_valid(self, form):
    'subject_template_name': self.subject_template_name,
    'request': self.request,
    }
    if is_admin_site:
    if self.is_admin_site:
    opts['domain_override'] = self.request.META['HTTP_HOST']
    form.save(**opts)
    return super(PasswordResetView, self).form_valid(form)
    @@ -390,7 +401,7 @@ def get_context_data(self, **kwargs):
    @method_decorator(sensitive_post_parameters())
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordResetView, self).dispatch(request, *args, **kwargs)
    return super(PasswordResetConfirmView, self).dispatch(request, *args, **kwargs)

    def password_reset_confirm(request, uidb36=None, token=None,
    template_name=None, token_generator=None,
    @@ -537,5 +548,5 @@ def password_change_done(request, template_name=None, post_change_redirect=None,
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_change_done = PasswordChangeDone.as_view(**kwargs)
    password_change_done = PasswordChangeDoneView.as_view(**kwargs)
    return password_change_done(request)
  4. @bmispelon bmispelon revised this gist Feb 18, 2012. 1 changed file with 25 additions and 28 deletions.
    53 changes: 25 additions & 28 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -43,36 +43,40 @@ class RedirectToMixin(object):
    name is configurable).
    In the absence of this parameter, a (configurable) default URL is used.
    """
    redirect_field_name = REDIRECT_FIELD_NAME
    default_redirect_to = None

    def get_redirect_field_name(self):
    return self.redirect_field_name

    def get_default_redirect_to(self):
    return self.default_redirect_to

    def get_redirect_to(self, default=None):
    def get_success_url(self):
    default = self.get_default_redirect_to()
    redirect_to = self.request.REQUEST.get(self.get_redirect_field_name(), '')

    if not redirect_to and default is not None:
    return default

    netloc = urlparse.urlparse(redirect_to)[1]
    if netloc and netloc != self.request.get_host():
    # Don't allow redirection to a different host.
    return '' if default is None else default

    return redirect_to
    return redirect_to or default


    class ProtectectedRedirectToMixin(RedirectToMixin):
    """
    Ensure the URL to be redirected to is on the same host.
    """
    def get_success_url(self):
    default = self.get_default_redirect_to()
    return self.get_redirect_to(default)
    redirect_to = super(ProtectectedRedirectToMixin, self).get_success_url()
    netloc = urlparse.urlparse(redirect_to)[1]

    if not netloc or netloc == self.request.get_host():
    return redirect_to

    return self.get_default_redirect_to()


    class LoginView(RedirectToMixin, CurrentAppMixin, generic.FormView):
    class LoginView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.FormView):
    """
    Displays the login form and handles the login action.
    """
    form_class = AuthenticationForm
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'registration/login.html'

    current_app = None
    @@ -116,14 +120,12 @@ def get_context_data(self, **kwargs):
    return ctx


    class LogoutView(RedirectToMixin, CurrentAppMixin, generic.TemplateView):
    class LogoutView(ProtectectedRedirectToMixin, CurrentAppMixin, generic.TemplateView):
    """
    Logs out the user and displays 'You are logged out' message.
    """
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name='registration/logged_out.html'

    next_page = None
    current_app = None
    extra_context = None

    @@ -136,18 +138,13 @@ def get_context_data(self, **kwargs):
    })
    context.update(self.extra_context or {})
    return context

    def get_default_redirect_to(self):
    return self.default_redirect_to or self.request.path

    def dispatch(self, request, *args, **kwargs): # TODO: GET, POST, ... ?
    auth_logout(request)
    redirect_to = self.get_success_url()
    if redirect_to:
    return HttpResponseRedirect(redirect_to)

    if self.next_page is None:
    context = self.get_context_data()
    return self.render_to_response(context)
    else:
    return HttpResponseRedirect(self.next_page or self.request.path)
    return HttpResponseRedirect(self.get_success_url())


    class LogoutThenLoginView(LogoutView):
    @@ -190,7 +187,7 @@ def logout(request, next_page=None, template_name=None,
    kwargs = {}

    if next_page is not None:
    kwargs["next_page"] = next_page
    kwargs["default_redirect_to"] = next_page
    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
  5. @bmispelon bmispelon revised this gist Feb 18, 2012. 1 changed file with 6 additions and 12 deletions.
    18 changes: 6 additions & 12 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -111,8 +111,7 @@ def get_context_data(self, **kwargs):
    "site_name": current_site.name,
    })

    if self.extra_context is not None:
    ctx.update(self.extra_context)
    ctx.update(self.extra_context or {})

    return ctx

    @@ -135,8 +134,7 @@ def get_context_data(self, **kwargs):
    'site_name': current_site.name,
    'title': _('Logged out')
    })
    if self.extra_context is not None:
    context.update(self.extra_context)
    context.update(self.extra_context or {})
    return context

    def dispatch(self, request, *args, **kwargs): # TODO: GET, POST, ... ?
    @@ -277,8 +275,7 @@ def form_valid(self, form):

    def get_context_data(self, **kwargs):
    context = super(PasswordResetView, self).get_context_data(**kwargs)
    if self.extra_context is not None:
    context.update(self.extra_context)
    context.update(self.extra_context or {})
    return context

    @method_decorator(csrf_protect)
    @@ -389,8 +386,7 @@ def get_context_data(self, **kwargs):
    context.update({
    'validlink': self.object is not None
    })
    if self.extra_context:
    context.update(self.extra_context)
    context.update(self.extra_context or {})
    return context

    # Doesn't need csrf_protect since no-one can guess the URL
    @@ -439,8 +435,7 @@ class PasswordResetComplete(CurrentAppMixin, generic.TemplateView):
    def get_context_data(self, **kwargs):
    context = super(PasswordResetComplete, self).get_context_data(**kwargs)
    context['login_url'] = settings.LOGIN_URL
    if self.extra_context:
    context.update(self.extra_context)
    context.update(self.extra_context or {})
    return context


    @@ -523,8 +518,7 @@ class PasswordChangeDoneView(CurrentAppMixin, generic.TemplateView):

    def get_context_data(self, **kwargs):
    context = super(PasswordChangeDoneView, self).get_context_data(**kwargs)
    if self.extra_context:
    context.update(self.extra_context)
    context.update(self.extra_context or {})
    return context

    @method_decorator(login_required)
  6. @bmispelon bmispelon revised this gist Feb 17, 2012. 1 changed file with 82 additions and 30 deletions.
    112 changes: 82 additions & 30 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,32 @@
    # See https://code.djangoproject.com/ticket/17209
    # https://code.djangoproject.com/ticket/17209
    import urlparse

    from django.conf import settings
    from django.core.urlresolvers import reverse
    from django.http import HttpResponseRedirect, QueryDict
    from django.template.response import TemplateResponse
    from django.utils.http import base36_to_int
    from django.utils.translation import ugettext as _
    from django.views.decorators.debug import sensitive_post_parameters
    from django.views.decorators.cache import never_cache
    from django.views.decorators.csrf import csrf_protect
    from django.views import generic

    # Avoid shadowing the login() and logout() views below.
    from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout
    from django.contrib.auth.decorators import login_required
    from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, PasswordChangeForm
    from django.contrib.auth.models import User
    from django.contrib.auth.tokens import default_token_generator
    from django.contrib.sites.models import get_current_site


    class CurrentAppMixin(object):
    """
    Add a current_app property on the view and pass it to the response class.
    """
    current_app = None

    def render_to_response(self, context, **response_kwargs):
    return self.response_class(
    request=self.request,
    @@ -11,6 +38,11 @@ def render_to_response(self, context, **response_kwargs):


    class RedirectToMixin(object):
    """
    Provide a success_url that takes into account a request parameter (whose
    name is configurable).
    In the absence of this parameter, a (configurable) default URL is used.
    """
    def get_redirect_field_name(self):
    return self.redirect_field_name

    @@ -19,11 +51,11 @@ def get_default_redirect_to(self):

    def get_redirect_to(self, default=None):
    redirect_to = self.request.REQUEST.get(self.get_redirect_field_name(), '')
    netloc = urlparse.urlparse(redirect_to)[1]

    if not redirect_to and default is not None:
    return default

    netloc = urlparse.urlparse(redirect_to)[1]
    if netloc and netloc != self.request.get_host():
    # Don't allow redirection to a different host.
    return '' if default is None else default
    @@ -35,7 +67,7 @@ def get_success_url(self):
    return self.get_redirect_to(default)


    class LoginView(RedirectToMixin, CurrentAppMixin, FormView):
    class LoginView(RedirectToMixin, CurrentAppMixin, generic.FormView):
    """
    Displays the login form and handles the login action.
    """
    @@ -85,7 +117,7 @@ def get_context_data(self, **kwargs):
    return ctx


    class LogoutView(RedirectToMixin, CurrentAppMixin, TemplateView):
    class LogoutView(RedirectToMixin, CurrentAppMixin, generic.TemplateView):
    """
    Logs out the user and displays 'You are logged out' message.
    """
    @@ -132,25 +164,25 @@ def next_page(self):


    def login(request, template_name=None, redirect_field_name=None,
    authentication_form=None, current_app=None, extra_context=None, *args, **kwargs):
    authentication_form=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for login -> LoginView
    """
    view_kwargs = {}
    kwargs = {}

    if template_name is not None:
    view_kwargs["template_name"] = template_name
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    view_kwargs["redirect_field_name"] = redirect_field_name
    kwargs["redirect_field_name"] = redirect_field_name
    if authentication_form is not None:
    view_kwargs["form_class"] = authentication_form
    kwargs["form_class"] = authentication_form
    if current_app is not None:
    view_kwargs["current_app"] = current_app
    kwargs["current_app"] = current_app
    if extra_context is not None:
    view_kwargs["extra_context"] = extra_context
    kwargs["extra_context"] = extra_context

    login_view = LoginView.as_view(**view_kwargs)
    return login_view(request, *args, **kwargs)
    view = LoginView.as_view(**kwargs)
    return view(request)

    def logout(request, next_page=None, template_name=None,
    redirect_field_name=None, current_app=None, extra_context=None):
    @@ -170,8 +202,8 @@ def logout(request, next_page=None, template_name=None,
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    logout_view = Logout.as_view(**kwargs)
    return logout_view(request)
    view = Logout.as_view(**kwargs)
    return view(request)

    def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
    """
    @@ -213,18 +245,22 @@ def redirect_to_login(next, login_url=None,


    class PasswordResetView(CurrentAppMixin, generic.FormView):
    """
    Ask for the user's email address and send a message containing a token
    allowing to reset the user's password.
    """
    template_name = "registration/password_reset_form.html"
    form_class = PasswordResetForm
    success_url = reverse_lazy('django.contrib.auth.views.password_reset_done')

    is_admin_site=False
    email_template_name = "registration/password_reset_email.html"
    subject_template_name = "registration/password_reset_subject.txt"
    token_generator = default_token_generator
    from_email = None
    current_app = None
    extra_context = None

    def form_valid(self, form):
    opts = {
    'use_https': self.request.is_secure(),
    @@ -282,11 +318,14 @@ def password_reset(request, is_admin_site=None, template_name=None,
    return password_reset(request)

    class PasswordResetDoneView(CurrentAppMixin, generic.TemplateView):
    """
    Show a confirmation message that a password reset email has been sent.
    """
    template_name = "registration/password_reset_done.html"

    current_app = None
    extra_context = None

    def get_context_data(self):
    return self.extra_context # TODO: does this work?

    @@ -296,14 +335,14 @@ def password_reset_done(request, template_name=None, current_app=None,
    Backwards Compatibility Shim for password_reset_done -> PassworResetDoneView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_done = PasswordResetDoneView.as_view(**kwargs)
    return password_reset_done(request)

    @@ -313,9 +352,12 @@ class PasswordResetConfirmView(CurrentAppMixin, generic.UpdateView):
    # In this CBV, form.user is a User instance if the token matches the uidb36,
    # even in the GET request, as opposed to the old view where form.user was
    # only set in POST).
    """
    Check that the given token is valid then prompt the user for a new pasword.
    """
    template_name = "registration/password_reset_confirm.html"
    form_class = SetPasswordForm
    success_url = reverse('django.contrib.auth.views.password_reset_complete')
    success_url = reverse_lazy('django.contrib.auth.views.password_reset_complete')

    token_generator = default_token_generator
    current_app = None
    @@ -341,7 +383,7 @@ def form_valid(self, form):
    if self.object is None:
    return self.form_invalid(form)
    return super(PasswordResetConfirmView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    context = super(PasswordResetConfirmView, self).get_context_data(**kwargs)
    context.update({
    @@ -365,9 +407,9 @@ def password_reset_confirm(request, uidb36=None, token=None,
    Backwards Compatibility Shim for password_reset_confirm -> PassworResetConfirmView
    """
    assert uidb36 is not None and token is not None # checked by URLconf

    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if token_generator is not None:
    @@ -380,17 +422,20 @@ def password_reset_confirm(request, uidb36=None, token=None,
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_confirm = PasswordResetConfirmView.as_view(**kwargs)
    return password_reset_confirm(request, uidb36=uidb36, token=token)


    class PasswordResetComplete(CurrentAppMixin, generic.TemplateView):
    """
    Show a confirmation message that the user's password has been reset.
    """
    template_name = "registration/password_reset_complete.html"

    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(PasswordResetComplete, self).get_context_data(**kwargs)
    context['login_url'] = settings.LOGIN_URL
    @@ -418,13 +463,17 @@ def password_reset_complete(request, template_name=None, current_app=None,


    class PasswordChangeView(CurrentAppMixin, generic.UpdateView):
    """
    Prompt the logged-in user for their old password and a new one and change
    the password if the old password is valid.
    """
    template_name = "registration/password_change_form.html"
    success_url = reverse('django.contrib.auth.views.password_change_done')
    success_url = reverse_lazy('django.contrib.auth.views.password_change_done')
    form_class = PasswordChangeForm

    current_app = None
    extra_context = None

    def get_object(self, queryset=None):
    return self.request.user

    @@ -464,11 +513,14 @@ def password_change(request, template_name=None, post_change_redirect=None,


    class PasswordChangeDoneView(CurrentAppMixin, generic.TemplateView):
    """
    Show a confirmation message that the user's password has been changed.
    """
    template_name = "registration/password_change_done.html"

    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(PasswordChangeDoneView, self).get_context_data(**kwargs)
    if self.extra_context:
  7. @bmispelon bmispelon revised this gist Feb 17, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    # See https://code.djangoproject.com/ticket/17209
    class CurrentAppMixin(object):
    def render_to_response(self, context, **response_kwargs):
    return self.response_class(
  8. @bmispelon bmispelon created this gist Feb 17, 2012.
    497 changes: 497 additions & 0 deletions django.contrib.auth.views.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,497 @@
    class CurrentAppMixin(object):
    def render_to_response(self, context, **response_kwargs):
    return self.response_class(
    request=self.request,
    template=self.get_template_names(),
    context=context,
    current_app=self.current_app.
    **response_kwargs
    )


    class RedirectToMixin(object):
    def get_redirect_field_name(self):
    return self.redirect_field_name

    def get_default_redirect_to(self):
    return self.default_redirect_to

    def get_redirect_to(self, default=None):
    redirect_to = self.request.REQUEST.get(self.get_redirect_field_name(), '')
    netloc = urlparse.urlparse(redirect_to)[1]

    if not redirect_to and default is not None:
    return default

    if netloc and netloc != self.request.get_host():
    # Don't allow redirection to a different host.
    return '' if default is None else default

    return redirect_to

    def get_success_url(self):
    default = self.get_default_redirect_to()
    return self.get_redirect_to(default)


    class LoginView(RedirectToMixin, CurrentAppMixin, FormView):
    """
    Displays the login form and handles the login action.
    """
    form_class = AuthenticationForm
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name = 'registration/login.html'

    current_app = None
    extra_context = None

    default_redirect_to = settings.LOGIN_REDIRECT_URL

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
    request.session.set_test_cookie()
    return super(LoginView, self).dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
    kwargs = super(LoginView, self).get_form_kwargs()
    kwargs.update({"request": self.request})
    return kwargs

    def form_valid(self, form):
    auth_login(self.request, form.get_user())

    if self.request.session.test_cookie_worked():
    self.request.session.delete_test_cookie()

    return super(LoginView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    ctx = super(LoginView, self).get_context_data(**kwargs)

    current_site = get_current_site(self.request)

    ctx.update({
    self.get_redirect_field_name(): self.get_success_url(),
    "site": current_site,
    "site_name": current_site.name,
    })

    if self.extra_context is not None:
    ctx.update(self.extra_context)

    return ctx


    class LogoutView(RedirectToMixin, CurrentAppMixin, TemplateView):
    """
    Logs out the user and displays 'You are logged out' message.
    """
    redirect_field_name = REDIRECT_FIELD_NAME
    template_name='registration/logged_out.html'

    next_page = None
    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(LogoutView, self).get_context_data(**kwargs)
    context.update({
    'site': current_site,
    'site_name': current_site.name,
    'title': _('Logged out')
    })
    if self.extra_context is not None:
    context.update(self.extra_context)
    return context

    def dispatch(self, request, *args, **kwargs): # TODO: GET, POST, ... ?
    auth_logout(request)
    redirect_to = self.get_success_url()
    if redirect_to:
    return HttpResponseRedirect(redirect_to)

    if self.next_page is None:
    context = self.get_context_data()
    return self.render_to_response(context)
    else:
    return HttpResponseRedirect(self.next_page or self.request.path)


    class LogoutThenLoginView(LogoutView):
    """
    Logs out the user if he is logged in. Then redirects to the log-in page.
    """
    login_url = None

    @property
    def next_page(self):
    return self.login_url or settings.LOGIN_URL


    def login(request, template_name=None, redirect_field_name=None,
    authentication_form=None, current_app=None, extra_context=None, *args, **kwargs):
    """
    Backwards Compatibility Shim for login -> LoginView
    """
    view_kwargs = {}

    if template_name is not None:
    view_kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    view_kwargs["redirect_field_name"] = redirect_field_name
    if authentication_form is not None:
    view_kwargs["form_class"] = authentication_form
    if current_app is not None:
    view_kwargs["current_app"] = current_app
    if extra_context is not None:
    view_kwargs["extra_context"] = extra_context

    login_view = LoginView.as_view(**view_kwargs)
    return login_view(request, *args, **kwargs)

    def logout(request, next_page=None, template_name=None,
    redirect_field_name=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for logout -> LogoutView
    """
    kwargs = {}

    if next_page is not None:
    kwargs["next_page"] = next_page
    if template_name is not None:
    kwargs["template_name"] = template_name
    if redirect_field_name is not None:
    kwargs["redirect_field_name"] = redirect_field_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    logout_view = Logout.as_view(**kwargs)
    return logout_view(request)

    def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for logout -> LogoutView
    """
    kwargs = {}

    if next_page is not None:
    kwargs["login_url"] = login_url
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context
    view = LogoutThenLoginView.as_view(**kwargs)
    return view(request)

    def redirect_to_login(next, login_url=None,
    redirect_field_name=REDIRECT_FIELD_NAME):
    """
    Redirects the user to the login page, passing the given 'next' page
    """
    if not login_url:
    login_url = settings.LOGIN_URL

    login_url_parts = list(urlparse.urlparse(login_url))
    if redirect_field_name:
    querystring = QueryDict(login_url_parts[4], mutable=True)
    querystring[redirect_field_name] = next
    login_url_parts[4] = querystring.urlencode(safe='/')

    return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))

    # 4 views for password reset:
    # - password_reset sends the mail
    # - password_reset_done shows a success message for the above
    # - password_reset_confirm checks the link the user clicked and
    # prompts for a new password
    # - password_reset_complete shows a success message for the above


    class PasswordResetView(CurrentAppMixin, generic.FormView):
    template_name = "registration/password_reset_form.html"
    form_class = PasswordResetForm
    success_url = reverse_lazy('django.contrib.auth.views.password_reset_done')

    is_admin_site=False
    email_template_name = "registration/password_reset_email.html"
    subject_template_name = "registration/password_reset_subject.txt"
    token_generator = default_token_generator
    from_email = None
    current_app = None
    extra_context = None

    def form_valid(self, form):
    opts = {
    'use_https': self.request.is_secure(),
    'token_generator': self.token_generator,
    'from_email': self.from_email,
    'email_template_name': self.email_template_name,
    'subject_template_name': self.subject_template_name,
    'request': self.request,
    }
    if is_admin_site:
    opts['domain_override'] = self.request.META['HTTP_HOST']
    form.save(**opts)
    return super(PasswordResetView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    context = super(PasswordResetView, self).get_context_data(**kwargs)
    if self.extra_context is not None:
    context.update(self.extra_context)
    return context

    @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordResetView, self).dispatch(request, *args, **kwargs)

    def password_reset(request, is_admin_site=None, template_name=None,
    email_template_name=None, subject_template_name=None,
    password_reset_form=None, token_generator=None,
    post_reset_redirect=None, from_email=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset -> PassworResetView
    """
    kwargs = {}

    if is_admin_site is not None:
    kwargs["is_admin_site"] = is_admin_site
    if template_name is not None:
    kwargs["template_name"] = template_name
    if email_template_name is not None:
    kwargs["email_template_name"] = email_template_name
    if password_reset_form is not None:
    kwargs["form_class"] = password_reset_form
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if from_email is not None:
    kwargs["from_email"] = from_email
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset = PasswordResetView.as_view(**kwargs)
    return password_reset(request)

    class PasswordResetDoneView(CurrentAppMixin, generic.TemplateView):
    template_name = "registration/password_reset_done.html"

    current_app = None
    extra_context = None

    def get_context_data(self):
    return self.extra_context # TODO: does this work?

    def password_reset_done(request, template_name=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_done -> PassworResetDoneView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_done = PasswordResetDoneView.as_view(**kwargs)
    return password_reset_done(request)


    class PasswordResetConfirmView(CurrentAppMixin, generic.UpdateView):
    # XXX: This one might have some backwards-compatibility issues in some corner cases.
    # In this CBV, form.user is a User instance if the token matches the uidb36,
    # even in the GET request, as opposed to the old view where form.user was
    # only set in POST).
    template_name = "registration/password_reset_confirm.html"
    form_class = SetPasswordForm
    success_url = reverse('django.contrib.auth.views.password_reset_complete')

    token_generator = default_token_generator
    current_app = None
    extra_context = None

    def get_object(self, queryset=None):
    try:
    pk = base36_to_int(self.kwargs['uidb36'])
    user = User.objects.get(pk=pk)
    except (ValueError, User.DoesNotExist):
    return None

    if not self.token_generator.check_token(user, self.kwargs['token']):
    return None
    return user

    def get_form_kwargs(self):
    kwargs = super(PasswordResetConfirmView, self).get_form_kwargs()
    kwargs['user'] = kwargs.pop('instance')
    return kwargs

    def form_valid(self, form):
    if self.object is None:
    return self.form_invalid(form)
    return super(PasswordResetConfirmView, self).form_valid(form)

    def get_context_data(self, **kwargs):
    context = super(PasswordResetConfirmView, self).get_context_data(**kwargs)
    context.update({
    'validlink': self.object is not None
    })
    if self.extra_context:
    context.update(self.extra_context)
    return context

    # Doesn't need csrf_protect since no-one can guess the URL
    @method_decorator(sensitive_post_parameters())
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordResetView, self).dispatch(request, *args, **kwargs)

    def password_reset_confirm(request, uidb36=None, token=None,
    template_name=None, token_generator=None,
    set_password_form=None, post_reset_redirect=None,
    current_app=None, extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_confirm -> PassworResetConfirmView
    """
    assert uidb36 is not None and token is not None # checked by URLconf

    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if token_generator is not None:
    kwargs["token_generator"] = token_generator
    if set_password_form is not None:
    kwargs["form_class"] = set_password_form
    if post_reset_redirect is not None:
    kwargs["success_url"] = post_reset_redirect
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_confirm = PasswordResetConfirmView.as_view(**kwargs)
    return password_reset_confirm(request, uidb36=uidb36, token=token)


    class PasswordResetComplete(CurrentAppMixin, generic.TemplateView):
    template_name = "registration/password_reset_complete.html"

    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(PasswordResetComplete, self).get_context_data(**kwargs)
    context['login_url'] = settings.LOGIN_URL
    if self.extra_context:
    context.update(self.extra_context)
    return context


    def password_reset_complete(request, template_name=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_reset_complete -> PasswordResetComplete
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_reset_complete = PasswordResetComplete.as_view(**kwargs)
    return password_reset_complete(request)


    class PasswordChangeView(CurrentAppMixin, generic.UpdateView):
    template_name = "registration/password_change_form.html"
    success_url = reverse('django.contrib.auth.views.password_change_done')
    form_class = PasswordChangeForm

    current_app = None
    extra_context = None

    def get_object(self, queryset=None):
    return self.request.user

    def get_form_kwargs(self):
    kwargs = super(PasswordChangeView, self).get_form_kwargs()
    kwargs['user'] = kwargs.pop('instance')

    return kwargs

    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordChangeView, self).dispatch(request, *args, **kwargs)

    def password_change(request, template_name=None, post_change_redirect=None,
    password_change_form=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_change -> PasswordChangeView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if post_change_redirect is not None:
    kwargs["success_url"] = post_change_redirect
    if password_change_form is not None:
    kwargs["form_class"] = password_change_form
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_change = PasswordChangeView.as_view(**kwargs)
    return password_change(request)


    class PasswordChangeDoneView(CurrentAppMixin, generic.TemplateView):
    template_name = "registration/password_change_done.html"

    current_app = None
    extra_context = None

    def get_context_data(self, **kwargs):
    context = super(PasswordChangeDoneView, self).get_context_data(**kwargs)
    if self.extra_context:
    context.update(self.extra_context)
    return context

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
    return super(PasswordChangeDoneView, self).dispatch(request, *args, **kwargs)

    def password_change_done(request, template_name=None, post_change_redirect=None,
    password_change_form=None, current_app=None,
    extra_context=None):
    """
    Backwards Compatibility Shim for password_change_done -> PasswordChangeDoneView
    """
    kwargs = {}

    if template_name is not None:
    kwargs["template_name"] = template_name
    if current_app is not None:
    kwargs["current_app"] = current_app
    if extra_context is not None:
    kwargs["extra_context"] = extra_context

    password_change_done = PasswordChangeDone.as_view(**kwargs)
    return password_change_done(request)