Merge branch 'release/0.9.2'
[philo.git] / philo / views.py
1 from django.conf import settings
2 from django.core.urlresolvers import resolve
3 from django.http import Http404, HttpResponseRedirect
4 from django.views.decorators.vary import vary_on_headers
5
6 from philo.exceptions import MIDDLEWARE_NOT_CONFIGURED
7
8
9 @vary_on_headers('Accept')
10 def node_view(request, path=None, **kwargs):
11         """
12         :func:`node_view` handles incoming requests by checking to make sure that:
13         
14         - the request has an attached :class:`.Node`.
15         - the attached :class:`~philo.models.nodes.Node` handles any remaining path beyond its location.
16         
17         If these conditions are not met, then :func:`node_view` will either raise :exc:`Http404` or, if it seems like the address was mistyped (for example missing a trailing slash), return an :class:`HttpResponseRedirect` to the correct address.
18         
19         Otherwise, :func:`node_view` will call the :class:`.Node`'s :meth:`~.Node.render_to_response` method, passing ``kwargs`` in as the ``extra_context``.
20         
21         """
22         if "philo.middleware.RequestNodeMiddleware" not in settings.MIDDLEWARE_CLASSES:
23                 raise MIDDLEWARE_NOT_CONFIGURED
24         
25         if not request.node:
26                 if settings.APPEND_SLASH and request.path != "/":
27                         path = request.path
28                         
29                         if path[-1] == "/":
30                                 path = path[:-1]
31                         else:
32                                 path += "/"
33                         
34                         view, args, kwargs = resolve(path)
35                         if view != node_view:
36                                 return HttpResponseRedirect(path)
37                 raise Http404
38         
39         node = request.node
40         subpath = request.node._subpath
41         
42         # Explicitly disallow trailing slashes if we are otherwise at a node's url.
43         if node._path != "/" and node._path[-1] == "/" and subpath == "/":
44                 return HttpResponseRedirect(node.get_absolute_url())
45         
46         if not node.handles_subpath(subpath):
47                 # If the subpath isn't handled, check settings.APPEND_SLASH. If
48                 # it's True, try to correct the subpath.
49                 if not settings.APPEND_SLASH:
50                         raise Http404
51                 
52                 if subpath[-1] == "/":
53                         subpath = subpath[:-1]
54                 else:
55                         subpath += "/"
56                 
57                 redirect_url = node.construct_url(subpath)
58                 
59                 if node.handles_subpath(subpath):
60                         return HttpResponseRedirect(redirect_url)
61                 
62                 # Perhaps there is a non-philo view at this address. Can we
63                 # resolve *something* there besides node_view? If not,
64                 # raise a 404.
65                 view, args, kwargs = resolve(redirect_url)
66                 
67                 if view == node_view:
68                         raise Http404
69                 else:
70                         return HttpResponseRedirect(redirect_url)
71         
72         return node.render_to_response(request, kwargs)