Simple middleware+decorator to handle age verification. Modeled after django.contrib.sessions.middleware
to add an attribute to request.user
called is_age_verified
with consideration to snippet 1002. Decorator modeled after django.contrib.auth.decorators.login_required
Installation:
Create `verify_age` URLconf in `urls.py`
Create age verification page that URLconf points to
Define `settings.VERIFY_AGE_URL` based on URLconf
Add `age_verification.AgeVerificationMiddleware` to `MIDDLEWARE_CLASSES`
Import both `age_verification_required` and `REDIRECT_FIELD_NAME` in `views.py`
Implement `age_verification.AgeVerification.verify` somewhere to set session attribute on successful verification.
Use `@age_verification_required` decorator for views requiring age verification
Example urls.py:
urlpatterns += patterns('mahalo.answers.views',
...
url(r'^verify_age/?$', 'verify_age', name="verify_age"),
...
Example settings.py:
...
VERIFY_URL = '/verify_age/'
...
MIDDLEWARE_CLASSES += (
...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'myproject.contrib.middleware.age_verification.AgeVerificationMiddleware',
...
Example views.py:
from myproject.contrib.decorators import age_verification_required, REDIRECT_FIELD_NAME
from myproject.contrib.middleware.age_verification import AgeVerification
...
@age_verification_required
def some_view(request):
return render_to_response("index.html", {})
def verify_age(request):
# project specific
template_vars = default_template(request)
# form was posted
if request.POST.has_key("month") and request.POST.has_key("day") and \
request.POST.has_key("year"):
# "verify" user
av = AgeVerification(request.session)
av.verify()
if request.POST.has_key(REDIRECT_FIELD_NAME):
return HttpResponseRedirect(request.POST[REDIRECT_FIELD_NAME])
else:
return HttpResponseRedirect(reverse("root"))
# no form posted, show it
else:
if request.GET.has_key(REDIRECT_FIELD_NAME):
template_vars["next"] = request.GET[REDIRECT_FIELD_NAME]
return render_to_response("verify_age.html", template_vars)
These examples assume age_verification.py
lives in myproject/contrib/middleware/
and decorators.py
lives in myproject/contrib/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 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)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.