Initial node_url_refactor commit. Revises node_url templatetag to accept args/kwargs...
[philo.git] / models / nodes.py
index b633542..c75700c 100644 (file)
@@ -3,8 +3,9 @@ from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
 from django.contrib.sites.models import Site
 from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect
 from django.contrib.contenttypes import generic
 from django.contrib.sites.models import Site
 from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect
+from django.core.exceptions import ViewDoesNotExist
 from django.core.servers.basehttp import FileWrapper
 from django.core.servers.basehttp import FileWrapper
-from django.core.urlresolvers import resolve, clear_url_caches
+from django.core.urlresolvers import resolve, clear_url_caches, reverse
 from django.template import add_to_builtins as register_templatetags
 from inspect import getargspec
 from philo.models.base import TreeEntity, Entity, QuerySetMapper, register_value_model
 from django.template import add_to_builtins as register_templatetags
 from inspect import getargspec
 from philo.models.base import TreeEntity, Entity, QuerySetMapper, register_value_model
@@ -29,13 +30,21 @@ class Node(TreeEntity):
                return False
        
        def render_to_response(self, request, path=None, subpath=None, extra_context=None):
                return False
        
        def render_to_response(self, request, path=None, subpath=None, extra_context=None):
-               return self.view._render_to_response(self, request, path, subpath, extra_context)
+               return self.view.render_to_response(self, request, path, subpath, extra_context)
        
        def get_absolute_url(self):
        
        def get_absolute_url(self):
-               root = Site.objects.get_current().root_node
                try:
                try:
-                       return '/%s' % self.get_path(root=root)
-               except AncestorDoesNotExist:
+                       root = Site.objects.get_current().root_node
+               except Site.DoesNotExist:
+                       root = None
+               
+               try:
+                       path = self.get_path(root=root)
+                       if path:
+                               path += '/'
+                       root_url = reverse('philo-root')
+                       return '%s%s' % (root_url, path)
+               except AncestorDoesNotExist, ViewDoesNotExist:
                        return None
        
        class Meta:
                        return None
        
        class Meta:
@@ -60,14 +69,14 @@ class View(Entity):
        def relationships_with_node(self, node):
                return QuerySetMapper(self.relationship_set, passthrough=node.relationships)
        
        def relationships_with_node(self, node):
                return QuerySetMapper(self.relationship_set, passthrough=node.relationships)
        
-       def _render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
+       def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
                extra_context = extra_context or {}
                view_about_to_render.send(sender=self, node=node, request=request, path=path, subpath=subpath, extra_context=extra_context)
                extra_context = extra_context or {}
                view_about_to_render.send(sender=self, node=node, request=request, path=path, subpath=subpath, extra_context=extra_context)
-               response = self.render_to_response(node, request, path, subpath, extra_context)
+               response = self.actually_render_to_response(node, request, path, subpath, extra_context)
                view_finished_rendering.send(sender=self, response=response)
                return response
        
                view_finished_rendering.send(sender=self, response=response)
                return response
        
-       def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
+       def actually_render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
                raise NotImplementedError('View subclasses must implement render_to_response.')
        
        class Meta:
                raise NotImplementedError('View subclasses must implement render_to_response.')
        
        class Meta:
@@ -80,9 +89,15 @@ _view_content_type_limiter.cls = View
 class MultiView(View):
        accepts_subpath = True
        
 class MultiView(View):
        accepts_subpath = True
        
-       urlpatterns = []
+       @property
+       def urlpatterns(self, obj):
+               raise NotImplementedError("MultiView subclasses must implement urlpatterns.")
+       
+       def get_reverse_params(self, obj):
+               """This method should return a view_name, args, kwargs tuple suitable for reversing a url for the given obj using self as the urlconf."""
+               raise NotImplementedError("MultiView subclasses must implement get_subpath.")
        
        
-       def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
+       def actually_render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
                clear_url_caches()
                if not subpath:
                        subpath = ""
                clear_url_caches()
                if not subpath:
                        subpath = ""
@@ -109,7 +124,7 @@ class Redirect(View):
        target = models.CharField(max_length=200, validators=[RedirectValidator()])
        status_code = models.IntegerField(choices=STATUS_CODES, default=302, verbose_name='redirect type')
        
        target = models.CharField(max_length=200, validators=[RedirectValidator()])
        status_code = models.IntegerField(choices=STATUS_CODES, default=302, verbose_name='redirect type')
        
-       def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
+       def actually_render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
                response = HttpResponseRedirect(self.target)
                response.status_code = self.status_code
                return response
                response = HttpResponseRedirect(self.target)
                response.status_code = self.status_code
                return response
@@ -124,7 +139,7 @@ class File(View):
        mimetype = models.CharField(max_length=255)
        file = models.FileField(upload_to='philo/files/%Y/%m/%d')
        
        mimetype = models.CharField(max_length=255)
        file = models.FileField(upload_to='philo/files/%Y/%m/%d')
        
-       def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
+       def actually_render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
                wrapper = FileWrapper(self.file)
                response = HttpResponse(wrapper, content_type=self.mimetype)
                response['Content-Length'] = self.file.size
                wrapper = FileWrapper(self.file)
                response = HttpResponse(wrapper, content_type=self.mimetype)
                response['Content-Length'] = self.file.size