Create a gist now

Instantly share code, notes, and snippets.

diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py
index 5805a31..5d35c0f 100644
--- a/django/contrib/auth/decorators.py
+++ b/django/contrib/auth/decorators.py
@@ -1,10 +1,11 @@
+import inspect
import urlparse
from functools import wraps
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import PermissionDenied
from django.utils.decorators import available_attrs
-
+from django.http import HttpRequest
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
@@ -13,11 +14,29 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
that takes the user object and returns True if the user passes.
"""
- def decorator(view_func):
- @wraps(view_func, assigned=available_attrs(view_func))
- def _wrapped_view(request, *args, **kwargs):
+ def decorator(obj):
+ # Case 1: decorated class.
+ if inspect.isclass(obj):
+ class LoginProtectedSubclass(obj):
+ @user_passes_test(test_func, login_url, redirect_field_name)
+ def dispatch(self, *args, **kwargs):
+ return super(LoginProtectedSubclass, self).dispatch(*args, **kwargs)
+ return LoginProtectedSubclass
+
+ # Case 2: decorated function or method.
+ @wraps(obj, assigned=available_attrs(obj))
+ def _wrapped_view(*args, **kwargs):
+ # Case 2A: wrapped function
+ if isinstance(args[0], HttpRequest):
+ request = args[0]
+ # Case 2B: wrapped method
+ elif isinstance(args[1], HttpRequest):
+ request = args[1]
+ else:
+ raise Exception("This should never happen.")
+
if test_func(request.user):
- return view_func(request, *args, **kwargs)
+ return obj(*args, **kwargs)
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment