After a long break I’m back to my blog. I moved from Turkey to Singapore, which is a little change in my life. Now the real thing, a middleware for Django.
This middleware auto-decorates each view function in a view module (views.py, or views/) with the decorators defined in settings.py.
An example setting is:
VIEW_AUTHENTICATORS = {
"module.views.secret": [
"django.contrib.auth.decorators.login_required",
"module.decorators.secret_access_required"],
"module.views.public": [
"django.contrib.auth.decorators.login_required",
"ptms.decorators.public_access_required"]
}
Think this middleware as a firewall. Whether you decorated your view functions or not, this ensures that your content is protected by using the decorators.
Note that this middleware needs to be at the end of the middlewares list because it always return an HttpResponse by calling the view function; which means no other middleware after this is executed.
Here is the function:
def process_view(self, request, view_func, view_args, view_kwargs):
if not hasattr(settings, "VIEW_AUTHENTICATORS"): return None
mauths = settings.VIEW_AUTHENTICATORS.keys()
module = view_func.__module__
# Trying to find if any authenticator is defined for this module
module_matches = [mauth for mauth in mauths if module.startswith(mauth)]
# if there is no match, bail out
if not module_matches: return None
# if there is a match...
authenticators = settings.VIEW_AUTHENTICATORS[module_matches[0]]
functions = []
# go on parsing the list
for function_path in authenticators:
try:
dot = function_path.rindex('.')
except ValueError:
raise exceptions.ImproperlyConfigured, '%s isn\'t a function path (error from settings.VIEW_AUTHENTICATORS)' % function_path
f_module, f_name = function_path[:dot], function_path[dot+1:]
try:
mod = import_module(f_module)
except ImportError, e:
raise exceptions.ImproperlyConfigured, 'Error importing module %s from settings.VIEW_AUTHENTICATORS: "%s"' % (f_module, e)
try:
f = getattr(mod, f_name)
except AttributeError:
raise exceptions.ImproperlyConfigured, 'View authenticator %s is not defined in %s' % (f_module, f_name)
functions.append(f)
def compose(f, g): return lambda *args, **kws: f(g(*args, **kws))
multi_compose = functools.partial(reduce, compose)
all_decorators = multi_compose(functions)
decorated_view = all_decorators(view_func)
return decorated_view(request, *view_args, **view_kwargs)
I await all the comments.