Fixed #3185 -- Made values for login, logout and post-login redirect URLs

configurable. This is a combined patch from Vasily Sulatskov, Marc Fargas and
Collin Grady.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@5072 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-04-25 08:49:57 +00:00
parent d744a660c4
commit 5dfe74f221
8 changed files with 65 additions and 20 deletions

View File

@ -312,6 +312,12 @@ BANNED_IPS = ()
AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',)
LOGIN_URL = '/accounts/login/'
LOGOUT_URL = '/accounts/logout/'
LOGIN_REDIRECT_URL = '/accounts/profile/'
########### ###########
# TESTING # # TESTING #
########### ###########

View File

@ -2,7 +2,6 @@ from django.core.exceptions import ImproperlyConfigured
SESSION_KEY = '_auth_user_id' SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend' BACKEND_SESSION_KEY = '_auth_user_backend'
LOGIN_URL = '/accounts/login/'
REDIRECT_FIELD_NAME = 'next' REDIRECT_FIELD_NAME = 'next'
def load_backend(path): def load_backend(path):

View File

@ -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 django.http import HttpResponseRedirect
from urllib import quote 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, 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 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. 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 _dec(view_func):
def _checklogin(request, *args, **kwargs): def _checklogin(request, *args, **kwargs):
if test_func(request.user): 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 Decorator for views that checks whether a user has a particular permission
enabled, redirecting to the log-in page if necessary. enabled, redirecting to the log-in page if necessary.

View File

@ -6,7 +6,7 @@ from django.template import RequestContext
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required 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'): def login(request, template_name='registration/login.html'):
"Displays the login form and handles the login action." "Displays the login form and handles the login action."
@ -17,7 +17,8 @@ def login(request, template_name='registration/login.html'):
if not errors: if not errors:
# Light security check -- make sure redirect_to isn't garbage. # Light security check -- make sure redirect_to isn't garbage.
if not redirect_to or '://' in redirect_to or ' ' in redirect_to: 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 from django.contrib.auth import login
login(request, manipulator.get_user()) login(request, manipulator.get_user())
request.session.delete_test_cookie() 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. # Redirect to this page until the session has been cleared.
return HttpResponseRedirect(next_page or request.path) 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." "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) 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" "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)) 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', def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',

View File

@ -3,7 +3,7 @@
<form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post"> <form {% if photos_optional or photos_required %}enctype="multipart/form-data" {% endif %}action="/comments/post/" method="post">
{% if user.is_authenticated %} {% if user.is_authenticated %}
<p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="/accounts/logout/">{% trans "Log out" %}</a>)</p> <p>{% trans "Username:" %} <strong>{{ user.username }}</strong> (<a href="{{ logout_url }}">{% trans "Log out" %}</a>)</p>
{% else %} {% else %}
<p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p> <p><label for="id_username">{% trans "Username:" %}</label> <input type="text" name="username" id="id_username" /><br />{% trans "Password:" %} <input type="password" name="password" id="id_password" /> (<a href="/accounts/password_reset/">{% trans "Forgotten your password?" %}</a>)</p>
{% endif %} {% endif %}

View File

@ -25,6 +25,7 @@ class CommentFormNode(template.Node):
self.is_public = is_public self.is_public = is_public
def render(self, context): def render(self, context):
from django.conf import settings
from django.utils.text import normalize_newlines from django.utils.text import normalize_newlines
import base64 import base64
context.push() context.push()
@ -64,6 +65,7 @@ class CommentFormNode(template.Node):
if self.rating_options: if self.rating_options:
context['rating_range'], context['rating_choices'] = Comment.objects.get_rating_options(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['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) default_form = loader.get_template(COMMENT_FORM)
output = default_form.render(context) output = default_form.render(context)
context.pop() context.pop()

View File

@ -387,14 +387,15 @@ introduced in Python 2.4::
``login_required`` does the following: ``login_required`` does the following:
* If the user isn't logged in, redirect to ``/accounts/login/``, passing * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
the current absolute URL in the query string as ``next``. For example: (``/accounts/login/`` by default), passing the current absolute URL
in the query string as ``next``. For example:
``/accounts/login/?next=/polls/3/``. ``/accounts/login/?next=/polls/3/``.
* If the user is logged in, execute the view normally. The view code is * If the user is logged in, execute the view normally. The view code is
free to assume the user is logged in. free to assume the user is logged in.
Note that you'll need to map the appropriate Django view to ``/accounts/login/``. Note that you'll need to map the appropriate Django view to ``settings.LOGIN_URL``.
To do this, add the following line to your URLconf:: For example, using the defaults, add the following line to your URLconf::
(r'^accounts/login/$', 'django.contrib.auth.views.login'), (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 * 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 successful, the view redirects to the URL specified in ``next``. If
``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is ``next`` isn't provided, it redirects to ``settings.LOGIN_REDIRECT_URL``
currently hard-coded). If login isn't successful, it redisplays the login (which defaults to ``/accounts/profile/``). If login isn't successful,
form. it redisplays the login form.
It's your responsibility to provide the login form in a template called It's your responsibility to provide the login form in a template called
``registration/login.html`` by default. This template gets passed three ``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:** **Optional arguments:**
* ``login_url``: The URL of the login page to redirect to. This * ``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`` ``django.contrib.auth.views.password_change``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -569,7 +570,7 @@ successful login.
**Optional arguments:** **Optional arguments:**
* ``login_url``: The URL of the login page to redirect to. This * ``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 Built-in manipulators
--------------------- ---------------------
@ -636,7 +637,7 @@ Note that ``user_passes_test`` does not automatically check that the ``User``
is not anonymous. is not anonymous.
``user_passes_test()`` takes an optional ``login_url`` argument, which lets you ``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:: Example in Python 2.3 syntax::
@ -680,7 +681,7 @@ parameter. Example::
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view) my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
As in the ``login_required`` decorator, ``login_url`` defaults to As in the ``login_required`` decorator, ``login_url`` defaults to
``'/accounts/login/'``. ``settings.LOGIN_URL``.
Limiting access to generic views Limiting access to generic views
-------------------------------- --------------------------------

View File

@ -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 you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime. 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 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, See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
TIME_FORMAT and YEAR_MONTH_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 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 It boils down to this: Use exactly one of either ``configure()`` or
``DJANGO_SETTINGS_MODULE``. Not both, and not neither. ``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
.. _@login_required: ../authentication/#the-login-required-decorator
Error reporting via e-mail Error reporting via e-mail
========================== ==========================