Saturday, November 28, 2009

django ssl decorator

I recently found myself needing a way to require some django views be accessed only via a secure channel, as in ssl. A quick search led me to this post. I was able to quickly get up and running with this snippet and a couple of standard view functions, but ran into problems when trying to decorate a FormWizard view. The problem lied in the fact that FormWizards are implemented as classes with overridden __call__ methods. Long story short, I reworked the decorator as a class to work with functions and classes implementing __call__.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
try:
  from functools import update_wrapper
except ImportError:
  from django.utils.functional import update_wrapper
 
class ssl_required(object):
  '''Decorator class to force ssl'''
  def __init__(self, func):
    self.func = func
    update_wrapper(self, func)
 
  def __get__(self, obj, cls=None):
    func = self.func.__get__(obj, cls)
    return ssl_required(func)
 
  def __call__(self, req, *args, **kwargs):
    if req.is_secure() or \
        not getattr(settings, 'HTTPS_SUPPORT', True):
      return self.func(req, *args, **kwargs)
    url = req.build_absolute_uri(req.get_full_path())
    url = url.replace('http://', 'https://')
    return HttpResponseRedirect(url)

No comments: