b90067a41859d8a44ddb651a81613f639c42ab11
[philo.git] / philo / middleware.py
1 from django.conf import settings
2 from django.contrib.sites.models import Site
3 from django.http import Http404
4
5 from philo.models import Node, View
6
7
8 class LazyNode(object):
9         def __get__(self, request, obj_type=None):
10                 if not hasattr(request, '_cached_node_path'):
11                         return None
12                 
13                 if not hasattr(request, '_found_node'):
14                         try:
15                                 current_site = Site.objects.get_current()
16                         except Site.DoesNotExist:
17                                 current_site = None
18                         
19                         path = request._cached_node_path
20                         trailing_slash = False
21                         if path[-1] == '/':
22                                 trailing_slash = True
23                         
24                         try:
25                                 node, subpath = Node.objects.get_with_path(path, root=getattr(current_site, 'root_node', None), absolute_result=False)
26                         except Node.DoesNotExist:
27                                 node = None
28                         else:
29                                 if subpath is None:
30                                         subpath = ""
31                                 subpath = "/" + subpath
32                                 
33                                 if not node.handles_subpath(subpath):
34                                         node = None
35                                 else:
36                                         if trailing_slash and subpath[-1] != "/":
37                                                 subpath += "/"
38                                         
39                                         node.subpath = subpath
40                         
41                         request._found_node = node
42                 
43                 return request._found_node
44
45
46 class RequestNodeMiddleware(object):
47         """Adds a ``node`` attribute, representing the currently-viewed node, to every incoming :class:`HttpRequest` object. This is required by :func:`philo.views.node_view`."""
48         def process_request(self, request):
49                 request.__class__.node = LazyNode()
50         
51         def process_view(self, request, view_func, view_args, view_kwargs):
52                 try:
53                         request._cached_node_path = view_kwargs['path']
54                 except KeyError:
55                         pass
56         
57         def process_exception(self, request, exception):
58                 if settings.DEBUG or not hasattr(request, 'node') or not request.node:
59                         return
60                 
61                 if isinstance(exception, Http404):
62                         error_view = request.node.attributes.get('Http404', None)
63                 else:
64                         error_view = request.node.attributes.get('Http500', None)
65                 
66                 if error_view is None or not isinstance(error_view, View):
67                         # Should this be duck-typing? Perhaps even no testing?
68                         return
69                 
70                 extra_context = {'exception': exception}
71                 return error_view.render_to_response(request, extra_context)