Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #5394 -- REDIRECT_FIELD_NAME is now configurable. Thanks, Petr …

…Marhoun, DavidReynolds and effbot

git-svn-id: http://code.djangoproject.com/svn/django/trunk@6206 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 55d6aebfecb527d64f50e608bb51cb5ea81f4c62 1 parent 0d52d2b
@adrianholovaty adrianholovaty authored
View
13 django/contrib/auth/decorators.py
@@ -2,7 +2,7 @@
from django.http import HttpResponseRedirect
from urllib import quote
-def user_passes_test(test_func, login_url=None):
+def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
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
@@ -15,20 +15,25 @@ def _dec(view_func):
def _checklogin(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
- return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
+ return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, quote(request.get_full_path())))
_checklogin.__doc__ = view_func.__doc__
_checklogin.__dict__ = view_func.__dict__
return _checklogin
return _dec
-login_required = user_passes_test(lambda u: u.is_authenticated())
-login_required.__doc__ = (
+def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
+ actual_decorator = user_passes_test(
+ lambda u: u.is_authenticated(),
+ redirect_field_name=redirect_field_name
)
+ if function:
+ return actual_decorator(function)
+ return actual_decorator
def permission_required(perm, login_url=None):
"""
View
10 django/contrib/auth/views.py
@@ -9,10 +9,10 @@
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.utils.translation import ugettext as _
-def login(request, template_name='registration/login.html'):
+def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
"Displays the login form and handles the login action."
manipulator = AuthenticationForm(request)
- redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
+ redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.POST:
errors = manipulator.get_validation_errors(request.POST)
if not errors:
@@ -35,7 +35,7 @@ def login(request, template_name='registration/login.html'):
return render_to_response(template_name, {
'form': oldforms.FormWrapper(manipulator, request.POST, errors),
- REDIRECT_FIELD_NAME: redirect_to,
+ redirect_field_name: redirect_to,
'site_name': current_site.name,
}, context_instance=RequestContext(request))
@@ -56,12 +56,12 @@ def logout_then_login(request, login_url=None):
login_url = settings.LOGIN_URL
return logout(request, login_url)
-def redirect_to_login(next, login_url=None):
+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:
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',
email_template_name='registration/password_reset_email.html'):
View
20 docs/authentication.txt
@@ -402,11 +402,29 @@ introduced in Python 2.4::
def my_view(request):
# ...
+In the Django development version, ``login_required`` also takes an optional
+``redirect_field_name`` parameter. Example::
+
+ from django.contrib.auth.decorators import login_required
+
+ def my_view(request):
+ # ...
+ my_view = login_required(redirect_field_name='redirect_to')(my_view)
+
+Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4::
+
+ from django.contrib.auth.decorators import login_required
+
+ @login_required(redirect_field_name='redirect_to')
+ def my_view(request):
+ # ...
+
``login_required`` does the following:
* 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:
+ in the query string as ``next`` or the value of ``redirect_field_name``.
+ 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.
View
16 tests/modeltests/test_client/models.py
@@ -250,6 +250,22 @@ def test_view_with_login(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['user'].username, 'testclient')
+ def test_view_with_login_and_custom_redirect(self):
+ "Request a page that is protected with @login_required(redirect_field_name='redirect_to')"
+
+ # Get the page without logging in. Should result in 302.
+ response = self.client.get('/test_client/login_protected_view_custom_redirect/')
+ self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/')
+
+ # Log in
+ login = self.client.login(username='testclient', password='password')
+ self.failUnless(login, 'Could not log in')
+
+ # Request a page that requires a login
+ response = self.client.get('/test_client/login_protected_view_custom_redirect/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['user'].username, 'testclient')
+
def test_view_with_bad_login(self):
"Request a page that is protected with @login, but use bad credentials"
View
1  tests/modeltests/test_client/urls.py
@@ -13,6 +13,7 @@
(r'^form_view/$', views.form_view),
(r'^form_view_with_template/$', views.form_view_with_template),
(r'^login_protected_view/$', views.login_protected_view),
+ (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
(r'^session_view/$', views.session_view),
(r'^broken_view/$', views.broken_view),
(r'^mail_sending_view/$', views.mail_sending_view),
View
8 tests/modeltests/test_client/views.py
@@ -122,6 +122,14 @@ def login_protected_view(request):
return HttpResponse(t.render(c))
login_protected_view = login_required(login_protected_view)
+def login_protected_view_changed_redirect(request):
+ "A simple view that is login protected with a custom redirect field set"
+ t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
+ c = Context({'user': request.user})
+
+ return HttpResponse(t.render(c))
+login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect)
+
def session_view(request):
"A view that modifies the session"
request.session['tobacconist'] = 'hovercraft'
Please sign in to comment.
Something went wrong with that request. Please try again.