diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index dc869ebd02..521caedbd0 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -312,6 +312,12 @@ BANNED_IPS = () AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) +LOGIN_URL = '/accounts/login/' + +LOGOUT_URL = '/accounts/logout/' + +LOGIN_REDIRECT_URL = '/accounts/profile/' + ########### # TESTING # ########### diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py index dd3b8152e6..8c92732f44 100644 --- a/django/contrib/auth/__init__.py +++ b/django/contrib/auth/__init__.py @@ -2,7 +2,6 @@ from django.core.exceptions import ImproperlyConfigured SESSION_KEY = '_auth_user_id' BACKEND_SESSION_KEY = '_auth_user_backend' -LOGIN_URL = '/accounts/login/' REDIRECT_FIELD_NAME = 'next' def load_backend(path): diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py index 37e948f8fe..2fb4a6f510 100644 --- a/django/contrib/auth/decorators.py +++ b/django/contrib/auth/decorators.py @@ -1,13 +1,16 @@ -from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME +from django.contrib.auth import REDIRECT_FIELD_NAME from django.http import HttpResponseRedirect from urllib import quote -def user_passes_test(test_func, login_url=LOGIN_URL): +def user_passes_test(test_func, login_url=None): """ Decorator for views that checks that the user passes the given test, redirecting to the log-in page if necessary. The test should be a callable that takes the user object and returns True if the user passes. """ + if not login_url: + from django.conf import settings + login_url = settings.LOGIN_URL def _dec(view_func): def _checklogin(request, *args, **kwargs): if test_func(request.user): @@ -27,7 +30,7 @@ login_required.__doc__ = ( """ ) -def permission_required(perm, login_url=LOGIN_URL): +def permission_required(perm, login_url=None): """ Decorator for views that checks whether a user has a particular permission enabled, redirecting to the log-in page if necessary. diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py index fda17b91fb..77350b9a8f 100644 --- a/django/contrib/auth/views.py +++ b/django/contrib/auth/views.py @@ -6,7 +6,7 @@ from django.template import RequestContext from django.contrib.sites.models import Site from django.http import HttpResponseRedirect from django.contrib.auth.decorators import login_required -from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME +from django.contrib.auth import REDIRECT_FIELD_NAME def login(request, template_name='registration/login.html'): "Displays the login form and handles the login action." @@ -17,7 +17,8 @@ def login(request, template_name='registration/login.html'): if not errors: # Light security check -- make sure redirect_to isn't garbage. if not redirect_to or '://' in redirect_to or ' ' in redirect_to: - redirect_to = '/accounts/profile/' + from django.conf import settings + redirect_to = settings.LOGIN_REDIRECT_URL from django.contrib.auth import login login(request, manipulator.get_user()) request.session.delete_test_cookie() @@ -41,12 +42,18 @@ def logout(request, next_page=None, template_name='registration/logged_out.html' # Redirect to this page until the session has been cleared. return HttpResponseRedirect(next_page or request.path) -def logout_then_login(request, login_url=LOGIN_URL): +def logout_then_login(request, login_url=None): "Logs out the user if he is logged in. Then redirects to the log-in page." + if not login_url: + from django.conf import settings + login_url = settings.LOGIN_URL return logout(request, login_url) -def redirect_to_login(next, login_url=LOGIN_URL): +def redirect_to_login(next, login_url=None): "Redirects the user to the login page, passing the given 'next' page" + if not login_url: + from django.conf import settings + login_url = settings.LOGIN_URL return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next)) def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', diff --git a/django/contrib/comments/templates/comments/form.html b/django/contrib/comments/templates/comments/form.html index c5aa7686a3..11eaa8d00d 100644 --- a/django/contrib/comments/templates/comments/form.html +++ b/django/contrib/comments/templates/comments/form.html @@ -3,7 +3,7 @@
{% if user.is_authenticated %} -

{% trans "Username:" %} {{ user.username }} ({% trans "Log out" %})

+

{% trans "Username:" %} {{ user.username }} ({% trans "Log out" %})

{% else %}


{% trans "Password:" %} ({% trans "Forgotten your password?" %})

{% endif %} diff --git a/django/contrib/comments/templatetags/comments.py b/django/contrib/comments/templatetags/comments.py index c3a2fd40d8..80d4bf24ab 100644 --- a/django/contrib/comments/templatetags/comments.py +++ b/django/contrib/comments/templatetags/comments.py @@ -25,6 +25,7 @@ class CommentFormNode(template.Node): self.is_public = is_public def render(self, context): + from django.conf import settings from django.utils.text import normalize_newlines import base64 context.push() @@ -64,6 +65,7 @@ class CommentFormNode(template.Node): if self.rating_options: context['rating_range'], context['rating_choices'] = Comment.objects.get_rating_options(self.rating_options) context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target']) + context['logout_url'] = settings.LOGOUT_URL default_form = loader.get_template(COMMENT_FORM) output = default_form.render(context) context.pop() diff --git a/docs/authentication.txt b/docs/authentication.txt index 01b218de65..f0902fad39 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -387,14 +387,15 @@ introduced in Python 2.4:: ``login_required`` does the following: - * If the user isn't logged in, redirect to ``/accounts/login/``, passing - the current absolute URL in the query string as ``next``. For example: + * If the user isn't logged in, redirect to ``settings.LOGIN_URL`` + (``/accounts/login/`` by default), passing the current absolute URL + in the query string as ``next``. For example: ``/accounts/login/?next=/polls/3/``. * If the user is logged in, execute the view normally. The view code is free to assume the user is logged in. -Note that you'll need to map the appropriate Django view to ``/accounts/login/``. -To do this, add the following line to your URLconf:: +Note that you'll need to map the appropriate Django view to ``settings.LOGIN_URL``. +For example, using the defaults, add the following line to your URLconf:: (r'^accounts/login/$', 'django.contrib.auth.views.login'), @@ -405,9 +406,9 @@ Here's what ``django.contrib.auth.views.login`` does: * If called via ``POST``, it tries to log the user in. If login is successful, the view redirects to the URL specified in ``next``. If - ``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is - currently hard-coded). If login isn't successful, it redisplays the login - form. + ``next`` isn't provided, it redirects to ``settings.LOGIN_REDIRECT_URL`` + (which defaults to ``/accounts/profile/``). If login isn't successful, + it redisplays the login form. It's your responsibility to provide the login form in a template called ``registration/login.html`` by default. This template gets passed three @@ -487,7 +488,7 @@ Logs a user out, then redirects to the login page. **Optional arguments:** * ``login_url``: The URL of the login page to redirect to. This - will default to ``/accounts/login/`` if not supplied. + will default to ``settings.LOGIN_URL`` if not supplied. ``django.contrib.auth.views.password_change`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -569,7 +570,7 @@ successful login. **Optional arguments:** * ``login_url``: The URL of the login page to redirect to. This - will default to ``/accounts/login/`` if not supplied. + will default to ``settings.LOGIN_URL`` if not supplied. Built-in manipulators --------------------- @@ -636,7 +637,7 @@ Note that ``user_passes_test`` does not automatically check that the ``User`` is not anonymous. ``user_passes_test()`` takes an optional ``login_url`` argument, which lets you -specify the URL for your login page (``/accounts/login/`` by default). +specify the URL for your login page (``settings.LOGIN_URL`` by default). Example in Python 2.3 syntax:: @@ -680,7 +681,7 @@ parameter. Example:: my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view) As in the ``login_required`` decorator, ``login_url`` defaults to -``'/accounts/login/'``. +``settings.LOGIN_URL``. Limiting access to generic views -------------------------------- diff --git a/docs/settings.txt b/docs/settings.txt index 35a6cc22e6..827ae55239 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -562,6 +562,21 @@ strings for translation, but the translation won't happen at runtime -- so you'll have to remember to wrap the languages in the *real* ``gettext()`` in any code that uses ``LANGUAGES`` at runtime. +LOGIN_URL +--------- + +Default: ``'/accounts/login/'`` + +The URL where requests are redirected for login, specially when using the +`@login_required`_ decorator. + +LOGOUT_URL +---------- + +Default: ``'/accounts/logout/'`` + +LOGIN_URL counterpart. + MANAGERS -------- @@ -620,6 +635,16 @@ locales have different formats. For example, U.S. English would say See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT and YEAR_MONTH_FORMAT. +LOGIN_REDIRECT_URL +------------------ + +Default: ``'/accounts/profile/'`` + +The URL where requests are redirected after login when the +``contrib.auth.login`` view gets no ``next`` parameter. + +This is used by the `@login_required`_ decorator, for example. + PREPEND_WWW ----------- @@ -1012,6 +1037,8 @@ Also, it's an error to call ``configure()`` more than once, or to call It boils down to this: Use exactly one of either ``configure()`` or ``DJANGO_SETTINGS_MODULE``. Not both, and not neither. +.. _@login_required: ../authentication/#the-login-required-decorator + Error reporting via e-mail ==========================