mirror of https://github.com/django/django.git
Added login_url argument to login_required decorator. Thanks mhlakhani and ericflo for the report and patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13723 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
27265f70a1
commit
bb00b28399
|
@ -30,13 +30,14 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
|
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
|
||||||
"""
|
"""
|
||||||
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(
|
actual_decorator = user_passes_test(
|
||||||
lambda u: u.is_authenticated(),
|
lambda u: u.is_authenticated(),
|
||||||
|
login_url=login_url,
|
||||||
redirect_field_name=redirect_field_name
|
redirect_field_name=redirect_field_name
|
||||||
)
|
)
|
||||||
if function:
|
if function:
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib.auth.tests.views import AuthViewsTestCase
|
||||||
|
|
||||||
|
class LoginRequiredTestCase(AuthViewsTestCase):
|
||||||
class LoginRequiredTestCase(TestCase):
|
|
||||||
"""
|
"""
|
||||||
Tests the login_required decorators
|
Tests the login_required decorators
|
||||||
"""
|
"""
|
||||||
|
urls = 'django.contrib.auth.tests.urls'
|
||||||
|
|
||||||
def testCallable(self):
|
def testCallable(self):
|
||||||
"""
|
"""
|
||||||
Check that login_required is assignable to callable objects.
|
Check that login_required is assignable to callable objects.
|
||||||
|
@ -23,3 +23,23 @@ class LoginRequiredTestCase(TestCase):
|
||||||
def normal_view(request):
|
def normal_view(request):
|
||||||
pass
|
pass
|
||||||
login_required(normal_view)
|
login_required(normal_view)
|
||||||
|
|
||||||
|
def testLoginRequired(self, view_url='/login_required/', login_url='/login/'):
|
||||||
|
"""
|
||||||
|
Check that login_required works on a simple view wrapped in a
|
||||||
|
login_required decorator.
|
||||||
|
"""
|
||||||
|
response = self.client.get(view_url)
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assert_(login_url in response['Location'])
|
||||||
|
self.login()
|
||||||
|
response = self.client.get(view_url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def testLoginRequiredNextUrl(self):
|
||||||
|
"""
|
||||||
|
Check that login_required works on a simple view wrapped in a
|
||||||
|
login_required decorator with a login_url set.
|
||||||
|
"""
|
||||||
|
self.testLoginRequired(view_url='/login_required_login_url/',
|
||||||
|
login_url='/somewhere/')
|
|
@ -1,5 +1,7 @@
|
||||||
from django.conf.urls.defaults import patterns
|
from django.conf.urls.defaults import patterns
|
||||||
from django.contrib.auth.urls import urlpatterns
|
from django.contrib.auth.urls import urlpatterns
|
||||||
|
from django.contrib.auth.views import password_reset
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.template import Template, RequestContext
|
from django.template import Template, RequestContext
|
||||||
|
|
||||||
|
@ -14,5 +16,7 @@ urlpatterns += patterns('',
|
||||||
(r'^logout/custom_query/$', 'django.contrib.auth.views.logout', dict(redirect_field_name='follow')),
|
(r'^logout/custom_query/$', 'django.contrib.auth.views.logout', dict(redirect_field_name='follow')),
|
||||||
(r'^logout/next_page/$', 'django.contrib.auth.views.logout', dict(next_page='/somewhere/')),
|
(r'^logout/next_page/$', 'django.contrib.auth.views.logout', dict(next_page='/somewhere/')),
|
||||||
(r'^remote_user/$', remote_user_auth_view),
|
(r'^remote_user/$', remote_user_auth_view),
|
||||||
|
(r'^login_required/$', login_required(password_reset)),
|
||||||
|
(r'^login_required_login_url/$', login_required(password_reset, login_url='/somewhere/')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,16 @@ class AuthViewsTestCase(TestCase):
|
||||||
settings.LANGUAGE_CODE = self.old_LANGUAGE_CODE
|
settings.LANGUAGE_CODE = self.old_LANGUAGE_CODE
|
||||||
settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS
|
settings.TEMPLATE_DIRS = self.old_TEMPLATE_DIRS
|
||||||
|
|
||||||
|
def login(self, password='password'):
|
||||||
|
response = self.client.post('/login/', {
|
||||||
|
'username': 'testclient',
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEquals(response.status_code, 302)
|
||||||
|
self.assert_(response['Location'].endswith(settings.LOGIN_REDIRECT_URL))
|
||||||
|
self.assert_(SESSION_KEY in self.client.session)
|
||||||
|
|
||||||
class PasswordResetTest(AuthViewsTestCase):
|
class PasswordResetTest(AuthViewsTestCase):
|
||||||
|
|
||||||
def test_email_not_found(self):
|
def test_email_not_found(self):
|
||||||
|
@ -118,15 +128,6 @@ class PasswordResetTest(AuthViewsTestCase):
|
||||||
|
|
||||||
class ChangePasswordTest(AuthViewsTestCase):
|
class ChangePasswordTest(AuthViewsTestCase):
|
||||||
|
|
||||||
def login(self, password='password'):
|
|
||||||
response = self.client.post('/login/', {
|
|
||||||
'username': 'testclient',
|
|
||||||
'password': password
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.assertEquals(response.status_code, 302)
|
|
||||||
self.assert_(response['Location'].endswith(settings.LOGIN_REDIRECT_URL))
|
|
||||||
|
|
||||||
def fail_login(self, password='password'):
|
def fail_login(self, password='password'):
|
||||||
response = self.client.post('/login/', {
|
response = self.client.post('/login/', {
|
||||||
'username': 'testclient',
|
'username': 'testclient',
|
||||||
|
@ -228,16 +229,6 @@ class LoginTest(AuthViewsTestCase):
|
||||||
class LogoutTest(AuthViewsTestCase):
|
class LogoutTest(AuthViewsTestCase):
|
||||||
urls = 'django.contrib.auth.tests.urls'
|
urls = 'django.contrib.auth.tests.urls'
|
||||||
|
|
||||||
def login(self, password='password'):
|
|
||||||
response = self.client.post('/login/', {
|
|
||||||
'username': 'testclient',
|
|
||||||
'password': password
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.assertEquals(response.status_code, 302)
|
|
||||||
self.assert_(response['Location'].endswith(settings.LOGIN_REDIRECT_URL))
|
|
||||||
self.assert_(SESSION_KEY in self.client.session)
|
|
||||||
|
|
||||||
def confirm_logged_out(self):
|
def confirm_logged_out(self):
|
||||||
self.assert_(SESSION_KEY not in self.client.session)
|
self.assert_(SESSION_KEY not in self.client.session)
|
||||||
|
|
||||||
|
|
|
@ -713,6 +713,17 @@ The login_required decorator
|
||||||
def my_view(request):
|
def my_view(request):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
:func:`~django.contrib.auth.decorators.login_required` also takes an
|
||||||
|
optional ``login_url`` parameter. Example::
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
@login_required(login_url='/accounts/login/')
|
||||||
|
def my_view(request):
|
||||||
|
...
|
||||||
|
|
||||||
:func:`~django.contrib.auth.decorators.login_required` does the following:
|
:func:`~django.contrib.auth.decorators.login_required` does the following:
|
||||||
|
|
||||||
* If the user isn't logged in, redirect to
|
* If the user isn't logged in, redirect to
|
||||||
|
@ -726,9 +737,9 @@ The login_required decorator
|
||||||
* 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
|
Note that if you don't specify the ``login_url`` parameter, you'll need to map
|
||||||
:setting:`settings.LOGIN_URL <LOGIN_URL>`. For example, using the defaults, add
|
the appropriate Django view to :setting:`settings.LOGIN_URL <LOGIN_URL>`. For
|
||||||
the following line to your URLconf::
|
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'),
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue