age_verification.py: class AgeVerificationMiddleware(object): """ Sets the age_verified request.user attribute """ def process_request(self, request): """sets the age_verified request.user attribute""" request.user.__class__.is_age_verified = AgeVerification(request.session) return None class AgeVerification: def __init__(self, session): self.session = session self.SESSION_VARIABLE = '_age_verified' def __call__(self): return self._get() def _get(self): return self.session.get(self.SESSION_VARIABLE, []) def verify(self): """ sets the session flag, determining age verification """ self.session[self.SESSION_VARIABLE] = True decorators.py: try: from functools import update_wrapper except ImportError: from django.utils.functional import update_wrapper # Python 2.3, 2.4 fallback. from django.http import HttpResponseRedirect from django.utils.http import urlquote REDIRECT_FIELD_NAME = "next" def user_passes_test(test_func, verify_age_url=None, redirect_field_name=REDIRECT_FIELD_NAME): """ Decorator for views that checks that the user passes the given test, redirecting to the age verification page if necessary. The test should be a callable that takes the user object and returns True if the user passes. """ def decorate(view_func): return _CheckAgeVerification(view_func, test_func, verify_age_url, redirect_field_name) return decorate def age_verification_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME): """ Decorator for views that checks that the user is age verified, redirecting to the age verification page if necessary. """ actual_decorator = user_passes_test( lambda u: u.is_age_verified(), redirect_field_name=redirect_field_name ) if function: return actual_decorator(function) return actual_decorator class _CheckAgeVerification(object): """ Class that checks that the user passes the given test, redirecting to the age verification page if necessary. If the test is passed, the view function is invoked. The test should be a callable that takes the user object and returns True if the user passes. We use a class here so that we can define __get__. This way, when a _CheckAgeVerification object is used as a method decorator, the view function is properly bound to its instance. Modeled after django.auth.decorators to be consistent """ def __init__(self, view_func, test_func, verify_age_url=None, redirect_field_name=REDIRECT_FIELD_NAME): if not verify_age_url: from django.conf import settings verify_age_url = settings.VERIFY_AGE_URL self.view_func = view_func self.test_func = test_func self.verify_age_url = verify_age_url self.redirect_field_name = redirect_field_name update_wrapper(self, view_func) def __get__(self, obj, cls=None): view_func = self.view_func.__get__(obj, cls) return _CheckAgeVerification(view_func, self.test_func, self.verify_age_url, self.redirect_field_name) def __call__(self, request, *args, **kwargs): if self.test_func(request.user): return self.view_func(request, *args, **kwargs) path = urlquote(request.get_full_path()) tup = self.verify_age_url, self.redirect_field_name, path return HttpResponseRedirect('%s?%s=%s' % tup)