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
This commit is contained in:
parent
0d52d2b2f9
commit
55d6aebfec
|
@ -2,7 +2,7 @@ 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=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 user_passes_test(test_func, login_url=None):
|
|||
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):
|
||||
"""
|
||||
|
|
|
@ -9,10 +9,10 @@ from django.contrib.auth.decorators import login_required
|
|||
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'):
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -250,6 +250,22 @@ class ClientTest(TestCase):
|
|||
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"
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ urlpatterns = patterns('',
|
|||
(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),
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue