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 django.http import HttpResponseRedirect
|
||||||
from urllib import quote
|
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,
|
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
|
||||||
|
@ -15,20 +15,25 @@ def user_passes_test(test_func, login_url=None):
|
||||||
def _checklogin(request, *args, **kwargs):
|
def _checklogin(request, *args, **kwargs):
|
||||||
if test_func(request.user):
|
if test_func(request.user):
|
||||||
return view_func(request, *args, **kwargs)
|
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.__doc__ = view_func.__doc__
|
||||||
_checklogin.__dict__ = view_func.__dict__
|
_checklogin.__dict__ = view_func.__dict__
|
||||||
|
|
||||||
return _checklogin
|
return _checklogin
|
||||||
return _dec
|
return _dec
|
||||||
|
|
||||||
login_required = user_passes_test(lambda u: u.is_authenticated())
|
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
|
||||||
login_required.__doc__ = (
|
|
||||||
"""
|
"""
|
||||||
Decorator for views that checks that the user is logged in, redirecting
|
Decorator for views that checks that the user is logged in, redirecting
|
||||||
to the log-in page if necessary.
|
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):
|
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.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.utils.translation import ugettext as _
|
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."
|
"Displays the login form and handles the login action."
|
||||||
manipulator = AuthenticationForm(request)
|
manipulator = AuthenticationForm(request)
|
||||||
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
|
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
||||||
if request.POST:
|
if request.POST:
|
||||||
errors = manipulator.get_validation_errors(request.POST)
|
errors = manipulator.get_validation_errors(request.POST)
|
||||||
if not errors:
|
if not errors:
|
||||||
|
@ -35,7 +35,7 @@ def login(request, template_name='registration/login.html'):
|
||||||
|
|
||||||
return render_to_response(template_name, {
|
return render_to_response(template_name, {
|
||||||
'form': oldforms.FormWrapper(manipulator, request.POST, errors),
|
'form': oldforms.FormWrapper(manipulator, request.POST, errors),
|
||||||
REDIRECT_FIELD_NAME: redirect_to,
|
redirect_field_name: redirect_to,
|
||||||
'site_name': current_site.name,
|
'site_name': current_site.name,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@ -56,12 +56,12 @@ def logout_then_login(request, login_url=None):
|
||||||
login_url = settings.LOGIN_URL
|
login_url = settings.LOGIN_URL
|
||||||
return logout(request, 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"
|
"Redirects the user to the login page, passing the given 'next' page"
|
||||||
if not login_url:
|
if not login_url:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
login_url = settings.LOGIN_URL
|
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',
|
||||||
email_template_name='registration/password_reset_email.html'):
|
email_template_name='registration/password_reset_email.html'):
|
||||||
|
|
|
@ -402,11 +402,29 @@ introduced in Python 2.4::
|
||||||
def my_view(request):
|
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:
|
``login_required`` does the following:
|
||||||
|
|
||||||
* If the user isn't logged in, redirect to ``settings.LOGIN_URL``
|
* If the user isn't logged in, redirect to ``settings.LOGIN_URL``
|
||||||
(``/accounts/login/`` by default), passing the current absolute 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/``.
|
``/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.
|
||||||
|
|
|
@ -250,6 +250,22 @@ class ClientTest(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.context['user'].username, 'testclient')
|
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):
|
def test_view_with_bad_login(self):
|
||||||
"Request a page that is protected with @login, but use bad credentials"
|
"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/$', views.form_view),
|
||||||
(r'^form_view_with_template/$', views.form_view_with_template),
|
(r'^form_view_with_template/$', views.form_view_with_template),
|
||||||
(r'^login_protected_view/$', views.login_protected_view),
|
(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'^session_view/$', views.session_view),
|
||||||
(r'^broken_view/$', views.broken_view),
|
(r'^broken_view/$', views.broken_view),
|
||||||
(r'^mail_sending_view/$', views.mail_sending_view),
|
(r'^mail_sending_view/$', views.mail_sending_view),
|
||||||
|
|
|
@ -122,6 +122,14 @@ def login_protected_view(request):
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
login_protected_view = login_required(login_protected_view)
|
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):
|
def session_view(request):
|
||||||
"A view that modifies the session"
|
"A view that modifies the session"
|
||||||
request.session['tobacconist'] = 'hovercraft'
|
request.session['tobacconist'] = 'hovercraft'
|
||||||
|
|
Loading…
Reference in New Issue