diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index cccba520238..4f08cc19a0c 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -322,13 +322,13 @@ class AdminSite(object): from django.contrib.auth.views import password_change url = reverse('admin:password_change_done', current_app=self.name) defaults = { - 'current_app': self.name, 'password_change_form': AdminPasswordChangeForm, 'post_change_redirect': url, 'extra_context': dict(self.each_context(request), **(extra_context or {})), } if self.password_change_template is not None: defaults['template_name'] = self.password_change_template + request.current_app = self.name return password_change(request, **defaults) def password_change_done(self, request, extra_context=None): @@ -337,11 +337,11 @@ class AdminSite(object): """ from django.contrib.auth.views import password_change_done defaults = { - 'current_app': self.name, 'extra_context': dict(self.each_context(request), **(extra_context or {})), } if self.password_change_done_template is not None: defaults['template_name'] = self.password_change_done_template + request.current_app = self.name return password_change_done(request, **defaults) def i18n_javascript(self, request): @@ -366,11 +366,11 @@ class AdminSite(object): """ from django.contrib.auth.views import logout defaults = { - 'current_app': self.name, 'extra_context': dict(self.each_context(request), **(extra_context or {})), } if self.logout_template is not None: defaults['template_name'] = self.logout_template + request.current_app = self.name return logout(request, **defaults) @never_cache @@ -399,10 +399,10 @@ class AdminSite(object): defaults = { 'extra_context': context, - 'current_app': self.name, 'authentication_form': self.login_form or AdminAuthenticationForm, 'template_name': self.login_template or 'admin/login.html', } + request.current_app = self.name return login(request, **defaults) def _build_app_dict(self, request, label=None): diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index e57d151d555..8bc4c0c9800 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -1,3 +1,4 @@ +import functools import warnings from django.conf import settings @@ -16,7 +17,9 @@ from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect, QueryDict from django.shortcuts import resolve_url from django.template.response import TemplateResponse -from django.utils.deprecation import RemovedInDjango110Warning +from django.utils.deprecation import ( + RemovedInDjango20Warning, RemovedInDjango110Warning, +) from django.utils.encoding import force_text from django.utils.http import is_safe_url, urlsafe_base64_decode from django.utils.six.moves.urllib.parse import urlparse, urlunparse @@ -26,13 +29,35 @@ from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters +def deprecate_current_app(func): + """ + Handle deprecation of the current_app parameter of the views. + """ + @functools.wraps(func) + def inner(*args, **kwargs): + if 'current_app' in kwargs: + warnings.warn( + "Passing `current_app` as a keyword argument is deprecated. " + "Instead the caller of `{0}` should set " + "`request.current_app`.".format(func.__name__), + RemovedInDjango20Warning + ) + current_app = kwargs.pop('current_app') + request = kwargs.get('request', None) + if request and current_app is not None: + request.current_app = current_app + return func(*args, **kwargs) + return inner + + +@deprecate_current_app @sensitive_post_parameters() @csrf_protect @never_cache def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME, authentication_form=AuthenticationForm, - current_app=None, extra_context=None): + extra_context=None): """ Displays the login form and handles the login action. """ @@ -65,16 +90,14 @@ def login(request, template_name='registration/login.html', if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) +@deprecate_current_app def logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name=REDIRECT_FIELD_NAME, - current_app=None, extra_context=None): + extra_context=None): """ Logs out the user and displays 'You are logged out' message. """ @@ -104,20 +127,18 @@ def logout(request, next_page=None, if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) -def logout_then_login(request, login_url=None, current_app=None, extra_context=None): +@deprecate_current_app +def logout_then_login(request, login_url=None, extra_context=None): """ Logs out the user if they are logged in. Then redirects to the log-in page. """ if not login_url: login_url = settings.LOGIN_URL login_url = resolve_url(login_url) - return logout(request, login_url, current_app=current_app, extra_context=extra_context) + return logout(request, login_url, extra_context=extra_context) def redirect_to_login(next, login_url=None, @@ -143,6 +164,7 @@ def redirect_to_login(next, login_url=None, # prompts for a new password # - password_reset_complete shows a success message for the above +@deprecate_current_app @csrf_protect def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', @@ -152,7 +174,6 @@ def password_reset(request, is_admin_site=False, token_generator=default_token_generator, post_reset_redirect=None, from_email=None, - current_app=None, extra_context=None, html_email_template_name=None): if post_reset_redirect is None: @@ -190,36 +211,32 @@ def password_reset(request, is_admin_site=False, if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) +@deprecate_current_app def password_reset_done(request, template_name='registration/password_reset_done.html', - current_app=None, extra_context=None): + extra_context=None): context = { 'title': _('Password reset sent'), } if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) # Doesn't need csrf_protect since no-one can guess the URL @sensitive_post_parameters() @never_cache +@deprecate_current_app def password_reset_confirm(request, uidb64=None, token=None, template_name='registration/password_reset_confirm.html', token_generator=default_token_generator, set_password_form=SetPasswordForm, post_reset_redirect=None, - current_app=None, extra_context=None): + extra_context=None): """ View that checks the hash in a password reset link and presents a form for entering a new password. @@ -259,15 +276,13 @@ def password_reset_confirm(request, uidb64=None, token=None, if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) +@deprecate_current_app def password_reset_complete(request, template_name='registration/password_reset_complete.html', - current_app=None, extra_context=None): + extra_context=None): context = { 'login_url': resolve_url(settings.LOGIN_URL), 'title': _('Password reset complete'), @@ -275,20 +290,18 @@ def password_reset_complete(request, if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) @sensitive_post_parameters() @csrf_protect @login_required +@deprecate_current_app def password_change(request, template_name='registration/password_change_form.html', post_change_redirect=None, password_change_form=PasswordChangeForm, - current_app=None, extra_context=None): + extra_context=None): if post_change_redirect is None: post_change_redirect = reverse('password_change_done') else: @@ -312,23 +325,18 @@ def password_change(request, if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) @login_required +@deprecate_current_app def password_change_done(request, template_name='registration/password_change_done.html', - current_app=None, extra_context=None): + extra_context=None): context = { 'title': _('Password change successful'), } if extra_context is not None: context.update(extra_context) - if current_app is not None: - request.current_app = current_app - return TemplateResponse(request, template_name, context) diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 9aaa5676a43..ae57f5e8f42 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -84,6 +84,8 @@ details on these changes. * ``django.template.loaders.eggs.Loader`` will be removed. +* The ``current_app`` parameter to the ``contrib.auth`` views will be removed. + .. _deprecation-removed-in-1.10: 1.10 diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 162430e502a..693ba7c5214 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -981,6 +981,24 @@ impossible to reverse the patterns if there was an application namespace with the same name. Includes that specify an instance namespace require that the included URLconf sets an application namespace. +``current_app`` parameter to ``contrib.auth`` views +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All views in ``django.contrib.auth.views`` have the following structure:: + + def view(request, ..., current_app=None, ...): + + ... + + if current_app is not None: + request.current_app = current_app + + return TemplateResponse(request, template_name, context) + +As of Django 1.8, ``current_app`` is set on the ``request`` object. For +consistency, these views will require the caller to set ``current_app`` on the +``request`` instead of passing it in a separate argument. + Miscellaneous ~~~~~~~~~~~~~ diff --git a/docs/topics/auth/default.txt b/docs/topics/auth/default.txt index 0ff6307cfb5..88703c60234 100644 --- a/docs/topics/auth/default.txt +++ b/docs/topics/auth/default.txt @@ -933,6 +933,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + Here's what ``django.contrib.auth.views.login`` does: * If called via ``GET``, it displays a login form that POSTs to the @@ -1059,6 +1064,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + **Template context:** * ``title``: The string "Logged out", localized. @@ -1100,6 +1110,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + .. function:: password_change(request[, template_name, post_change_redirect, password_change_form, current_app, extra_context]) Allows a user to change their password. @@ -1127,6 +1142,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + **Template context:** * ``form``: The password change form (see ``password_change_form`` above). @@ -1150,6 +1170,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + .. function:: password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email, current_app, extra_context, html_email_template_name]) Allows a user to reset their password by generating a one-time use link @@ -1216,6 +1241,11 @@ implementation details see :ref:`using-the-views`. The ``is_admin_site`` argument is deprecated and will be removed in Django 1.10. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + **Template context:** * ``form``: The form (see ``password_reset_form`` above) for resetting @@ -1281,6 +1311,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + .. function:: password_reset_confirm(request[, uidb64, token, template_name, token_generator, set_password_form, post_reset_redirect, current_app, extra_context]) Presents a form for entering a new password. @@ -1322,6 +1357,11 @@ implementation details see :ref:`using-the-views`. * ``validlink``: Boolean, True if the link (combination of ``uidb64`` and ``token``) is valid or unused yet. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + .. function:: password_reset_complete(request[,template_name, current_app, extra_context]) Presents a view which informs the user that the password has been @@ -1341,6 +1381,11 @@ implementation details see :ref:`using-the-views`. * ``extra_context``: A dictionary of context data that will be added to the default context data passed to the template. + .. deprecated:: 1.9 + + The ``current_app`` parameter is deprecated and will be removed in + Django 2.0. Callers should set ``request.current_app`` instead. + Helper functions ----------------