Skip to content

Instantly share code, notes, and snippets.

@ulope
Created June 9, 2011 20:41
Show Gist options
  • Save ulope/1017687 to your computer and use it in GitHub Desktop.
Save ulope/1017687 to your computer and use it in GitHub Desktop.
django #15552 patch v1
From cccb047c79211bfa3f89760a206009f706168728 Mon Sep 17 00:00:00 2001
From: Ulrich Petri <ulo@ulo.pe>
Date: Thu, 9 Jun 2011 22:38:33 +0200
Subject: [PATCH] Refactored settings.LOGIN_URL, LOGIN_REDIRECT_URL to use the logic from django.shortcuts.redirect (i.e. allow view names in LOGIN_URL, et. al.)
---
django/contrib/auth/decorators.py | 5 ++-
django/contrib/auth/tests/decorators.py | 2 +-
django/contrib/auth/views.py | 13 +++++---
django/shortcuts/__init__.py | 19 +----------
django/utils/url.py | 33 ++++++++++++++++++++
.../comment_tests/tests/__init__.py | 2 +-
.../regressiontests/comment_tests/urls_default.py | 9 +++++
tests/runtests.py | 2 +-
8 files changed, 58 insertions(+), 27 deletions(-)
create mode 100644 django/utils/url.py
create mode 100644 tests/regressiontests/comment_tests/urls_default.py
diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index 00a6bce..c0aa1c4 100644
--- a/django/contrib/auth/decorators.py
+++ b/django/contrib/auth/decorators.py
@@ -3,6 +3,7 @@ from functools import wraps
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.utils.decorators import available_attrs
+from django.utils.url import resolve_url
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
@@ -20,8 +21,8 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
path = request.build_absolute_uri()
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
- login_scheme, login_netloc = urlparse.urlparse(login_url or
- settings.LOGIN_URL)[:2]
+ login_scheme, login_netloc = urlparse.urlparse(
+ resolve_url(login_url or settings.LOGIN_URL))[:2]
current_scheme, current_netloc = urlparse.urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
diff --git a/django/contrib/auth/tests/decorators.py b/django/contrib/auth/tests/decorators.py
index bd3f011..dd41a32 100644
--- a/django/contrib/auth/tests/decorators.py
+++ b/django/contrib/auth/tests/decorators.py
@@ -25,7 +25,7 @@ class LoginRequiredTestCase(AuthViewsTestCase):
pass
login_required(normal_view)
- def testLoginRequired(self, view_url='/login_required/', login_url=settings.LOGIN_URL):
+ 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.
diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
index 4995f89..8d63177 100644
--- a/django/contrib/auth/views.py
+++ b/django/contrib/auth/views.py
@@ -6,6 +6,7 @@ from django.http import HttpResponseRedirect, QueryDict
from django.template.response import TemplateResponse
from django.utils.http import base36_to_int
from django.utils.translation import ugettext as _
+from django.utils.url import resolve_url
from django.views.decorators.debug import sensitive_post_parameters
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
@@ -34,16 +35,16 @@ def login(request, template_name='registration/login.html',
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
- netloc = urlparse.urlparse(redirect_to)[1]
-
# Use default setting if redirect_to is empty
if not redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL
+ redirect_to = resolve_url(redirect_to)
+ netloc = urlparse.urlparse(redirect_to)[1]
# Heavier security check -- don't allow redirection to a different
# host.
- elif netloc and netloc != request.get_host():
- redirect_to = settings.LOGIN_REDIRECT_URL
+ if netloc and netloc != request.get_host():
+ redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security checks complete. Log the user in.
auth_login(request, form.get_user())
@@ -106,6 +107,7 @@ def logout_then_login(request, login_url=None, current_app=None, extra_context=N
"""
if not login_url:
login_url = settings.LOGIN_URL
+ login_url = resolve_url(login_url)
return logout(request, login_url, current_app=current_app, extra_context=extra_context)
def redirect_to_login(next, login_url=None,
@@ -115,6 +117,7 @@ def redirect_to_login(next, login_url=None,
"""
if not login_url:
login_url = settings.LOGIN_URL
+ login_url = resolve_url(login_url)
login_url_parts = list(urlparse.urlparse(login_url))
if redirect_field_name:
@@ -223,7 +226,7 @@ def password_reset_complete(request,
template_name='registration/password_reset_complete.html',
current_app=None, extra_context=None):
context = {
- 'login_url': settings.LOGIN_URL
+ 'login_url': resolve_url(settings.LOGIN_URL)
}
if extra_context is not None:
context.update(extra_context)
diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
index 9f97cae..4dc74d3 100644
--- a/django/shortcuts/__init__.py
+++ b/django/shortcuts/__init__.py
@@ -10,6 +10,7 @@ from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
from django.core import urlresolvers
+from django.utils.url import resolve_url
def render_to_response(*args, **kwargs):
"""
@@ -66,23 +67,7 @@ def redirect(to, *args, **kwargs):
else:
redirect_class = HttpResponseRedirect
- # If it's a model, use get_absolute_url()
- if hasattr(to, 'get_absolute_url'):
- return redirect_class(to.get_absolute_url())
-
- # Next try a reverse URL resolution.
- try:
- return redirect_class(urlresolvers.reverse(to, args=args, kwargs=kwargs))
- except urlresolvers.NoReverseMatch:
- # If this is a callable, re-raise.
- if callable(to):
- raise
- # If this doesn't "feel" like a URL, re-raise.
- if '/' not in to and '.' not in to:
- raise
-
- # Finally, fall back and assume it's a URL
- return redirect_class(to)
+ return redirect_class(resolve_url(to, *args, **kwargs))
def _get_queryset(klass):
"""
diff --git a/django/utils/url.py b/django/utils/url.py
new file mode 100644
index 0000000..f7d0e0b
--- /dev/null
+++ b/django/utils/url.py
@@ -0,0 +1,33 @@
+from django.core import urlresolvers
+
+def resolve_url(to, *args, **kwargs):
+ """
+ Returns an URL apropriate for the arguments
+ passed.
+
+ The arguments could be:
+
+ * A model: the model's `get_absolute_url()` function will be called.
+
+ * A view name, possibly with arguments: `urlresolvers.reverse()` will
+ be used to reverse-resolve the name.
+
+ * A URL, which will be returned as-is.
+ """
+ # If it's a model, use get_absolute_url()
+ if hasattr(to, 'get_absolute_url'):
+ return to.get_absolute_url()
+
+ # Next try a reverse URL resolution.
+ try:
+ return urlresolvers.reverse(to, args=args, kwargs=kwargs)
+ except urlresolvers.NoReverseMatch:
+ # If this is a callable, re-raise.
+ if callable(to):
+ raise
+ # If this doesn't "feel" like a URL, re-raise.
+ if '/' not in to and '.' not in to:
+ raise
+
+ # Finally, fall back and assume it's a URL
+ return to
diff --git a/tests/regressiontests/comment_tests/tests/__init__.py b/tests/regressiontests/comment_tests/tests/__init__.py
index 88c6f33..7fc5e29 100644
--- a/tests/regressiontests/comment_tests/tests/__init__.py
+++ b/tests/regressiontests/comment_tests/tests/__init__.py
@@ -12,7 +12,7 @@ CT = ContentType.objects.get_for_model
# Helper base class for comment tests that need data.
class CommentTestCase(TestCase):
fixtures = ["comment_tests"]
- urls = 'django.contrib.comments.urls'
+ urls = 'regressiontests.comment_tests.urls_default'
def createSomeComments(self):
# Two anonymous comments on two different objects
diff --git a/tests/regressiontests/comment_tests/urls_default.py b/tests/regressiontests/comment_tests/urls_default.py
new file mode 100644
index 0000000..bfce8ff
--- /dev/null
+++ b/tests/regressiontests/comment_tests/urls_default.py
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ (r'^', include('django.contrib.comments.urls')),
+
+ # Provide the auth system login and logout views
+ (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
+ (r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
+)
diff --git a/tests/runtests.py b/tests/runtests.py
index 6da3299..77c9281 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -113,7 +113,7 @@ def setup(verbosity, test_labels):
settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),)
settings.USE_I18N = True
settings.LANGUAGE_CODE = 'en'
- settings.LOGIN_URL = '/accounts/login/'
+ settings.LOGIN_URL = 'django.contrib.auth.views.login'
settings.MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
--
1.7.0.2+GitX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment