web/lib/django/contrib/auth/decorators.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 try:
     1 try:
     2     from functools import update_wrapper
     2     from functools import update_wrapper, wraps
     3 except ImportError:
     3 except ImportError:
     4     from django.utils.functional import update_wrapper  # Python 2.3, 2.4 fallback.
     4     from django.utils.functional import update_wrapper, wraps  # Python 2.4 fallback.
     5 
     5 
     6 from django.contrib.auth import REDIRECT_FIELD_NAME
     6 from django.contrib.auth import REDIRECT_FIELD_NAME
     7 from django.http import HttpResponseRedirect
     7 from django.http import HttpResponseRedirect
       
     8 from django.utils.decorators import available_attrs
     8 from django.utils.http import urlquote
     9 from django.utils.http import urlquote
       
    10 
     9 
    11 
    10 def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    12 def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    11     """
    13     """
    12     Decorator for views that checks that the user passes the given test,
    14     Decorator for views that checks that the user passes the given test,
    13     redirecting to the log-in page if necessary. The test should be a callable
    15     redirecting to the log-in page if necessary. The test should be a callable
    14     that takes the user object and returns True if the user passes.
    16     that takes the user object and returns True if the user passes.
    15     """
    17     """
    16     def decorate(view_func):
    18     if not login_url:
    17         return _CheckLogin(view_func, test_func, login_url, redirect_field_name)
    19         from django.conf import settings
    18     return decorate
    20         login_url = settings.LOGIN_URL
       
    21 
       
    22     def decorator(view_func):
       
    23         def _wrapped_view(request, *args, **kwargs):
       
    24             if test_func(request.user):
       
    25                 return view_func(request, *args, **kwargs)
       
    26             path = urlquote(request.get_full_path())
       
    27             tup = login_url, redirect_field_name, path
       
    28             return HttpResponseRedirect('%s?%s=%s' % tup)
       
    29         return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
       
    30     return decorator
       
    31 
    19 
    32 
    20 def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
    33 def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
    21     """
    34     """
    22     Decorator for views that checks that the user is logged in, redirecting
    35     Decorator for views that checks that the user is logged in, redirecting
    23     to the log-in page if necessary.
    36     to the log-in page if necessary.
    28     )
    41     )
    29     if function:
    42     if function:
    30         return actual_decorator(function)
    43         return actual_decorator(function)
    31     return actual_decorator
    44     return actual_decorator
    32 
    45 
       
    46 
    33 def permission_required(perm, login_url=None):
    47 def permission_required(perm, login_url=None):
    34     """
    48     """
    35     Decorator for views that checks whether a user has a particular permission
    49     Decorator for views that checks whether a user has a particular permission
    36     enabled, redirecting to the log-in page if necessary.
    50     enabled, redirecting to the log-in page if necessary.
    37     """
    51     """
    38     return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
    52     return user_passes_test(lambda u: u.has_perm(perm), login_url=login_url)
    39 
       
    40 class _CheckLogin(object):
       
    41     """
       
    42     Class that checks that the user passes the given test, redirecting to
       
    43     the log-in page if necessary. If the test is passed, the view function
       
    44     is invoked. The test should be a callable that takes the user object
       
    45     and returns True if the user passes.
       
    46 
       
    47     We use a class here so that we can define __get__. This way, when a
       
    48     _CheckLogin object is used as a method decorator, the view function
       
    49     is properly bound to its instance.
       
    50     """
       
    51     def __init__(self, view_func, test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
       
    52         if not login_url:
       
    53             from django.conf import settings
       
    54             login_url = settings.LOGIN_URL
       
    55         self.view_func = view_func
       
    56         self.test_func = test_func
       
    57         self.login_url = login_url
       
    58         self.redirect_field_name = redirect_field_name
       
    59         
       
    60         # We can't blindly apply update_wrapper because it udpates __dict__ and 
       
    61         # if the view function is already a _CheckLogin object then 
       
    62         # self.test_func and friends will get stomped. However, we also can't 
       
    63         # *not* update the wrapper's dict because then view function attributes
       
    64         # don't get updated into the wrapper. So we need to split the
       
    65         # difference: don't let update_wrapper update __dict__, but then update
       
    66         # the (parts of) __dict__ that we care about ourselves.
       
    67         update_wrapper(self, view_func, updated=())
       
    68         for k in view_func.__dict__:
       
    69             if k not in self.__dict__:
       
    70                 self.__dict__[k] = view_func.__dict__[k]
       
    71 
       
    72     def __get__(self, obj, cls=None):
       
    73         view_func = self.view_func.__get__(obj, cls)
       
    74         return _CheckLogin(view_func, self.test_func, self.login_url, self.redirect_field_name)
       
    75     
       
    76     def __call__(self, request, *args, **kwargs):
       
    77         if self.test_func(request.user):
       
    78             return self.view_func(request, *args, **kwargs)
       
    79         path = urlquote(request.get_full_path())
       
    80         tup = self.login_url, self.redirect_field_name, path
       
    81         return HttpResponseRedirect('%s?%s=%s' % tup)