from django.db import models
from django.conf import settings
from philo.models import Tag, Titled, Entity, MultiView, Page, register_value_model
+from philo.exceptions import ViewCanNotProvideSubpath
from django.conf.urls.defaults import url, patterns
+from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponse
from datetime import datetime
from philo.contrib.penfield.utils import paginate
def __unicode__(self):
return u'BlogView for %s' % self.blog.title
+ def get_subpath(self, obj):
+ if isinstance(obj, BlogEntry):
+ if obj.blog == self.blog:
+ entry_view_args = {'slug': obj.slug}
+ if self.entry_permalink_style in 'DMY':
+ entry_view_args.update({'year': str(obj.date.year).zfill(4)})
+ if self.entry_permalink_style in 'DM':
+ entry_view_args.update({'month': str(obj.date.month).zfill(2)})
+ if self.entry_permalink_style == 'D':
+ entry_view_args.update({'day': str(obj.date.day).zfill(2)})
+ return reverse(self.entry_view, urlconf=self, kwargs=entry_view_args)
+ elif isinstance(obj, Tag):
+ if obj in self.blog.entry_tags:
+ return reverse(self.tag_view, urlconf=self, kwargs={'tag_slugs': obj.slug})
+ raise ViewCanNotProvideSubpath
+
@property
def urlpatterns(self):
base_patterns = patterns('',
--- /dev/null
+class ViewDoesNotProvideSubpaths(Exception):
+ """ Raised by get_subpath when the View does not provide subpaths (the default). """
+ silent_variable_failure = True
+
+class ViewCanNotProvideSubpath(Exception):
+ """ Raised by get_subpath when the View can not provide a subpath for the supplied object. """
+ silent_variable_failure = True
\ No newline at end of file
parent = models.ForeignKey('self', related_name='children', null=True, blank=True)
slug = models.SlugField()
- def get_path(self, pathsep='/', field='slug'):
- path = getattr(self, field, '?')
- parent = self.parent
+ def has_ancestor(self, ancestor):
+ parent = self
while parent:
- path = getattr(parent, field, '?') + pathsep + path
+ if parent == ancestor:
+ return True
parent = parent.parent
- return path
+ return False
+
+ def get_path(self, root=None, pathsep='/', field='slug'):
+ if root is not None and self.has_ancestor(root):
+ path = ''
+ parent = self
+ while parent and parent != root:
+ path = getattr(parent, field, '?') + pathsep + path
+ parent = parent.parent
+ return path
+ else:
+ path = getattr(self, field, '?')
+ parent = self.parent
+ while parent and parent != root:
+ path = getattr(parent, field, '?') + pathsep + path
+ parent = parent.parent
+ return path
path = property(get_path)
def __unicode__(self):
from django.http import HttpResponse, HttpResponseServerError, HttpResponseRedirect
from django.core.servers.basehttp import FileWrapper
from django.core.urlresolvers import resolve
+from django.template import add_to_builtins as register_templatetags
from inspect import getargspec
from philo.models.base import TreeEntity, Entity, QuerySetMapper
from philo.utils import ContentTypeSubclassLimiter
from philo.validators import RedirectValidator
+from philo.exceptions import ViewDoesNotProvideSubpaths
_view_content_type_limiter = ContentTypeSubclassLimiter(None)
@property
def accepts_subpath(self):
- return self.view.accepts_subpath
+ if self.view:
+ return self.view.accepts_subpath
+ 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)
accepts_subpath = False
+ def get_subpath(self, obj):
+ raise ViewDoesNotProvideSubpaths
+
def attributes_with_node(self, node):
return QuerySetMapper(self.attribute_set, passthrough=node.attributes)
app_label = 'philo'
def __unicode__(self):
- return self.file.name
\ No newline at end of file
+ return self.file.name
+
+
+register_templatetags('philo.templatetags.nodes')
\ No newline at end of file
def render_to_response(self, node, request, path=None, subpath=None, extra_context=None):
context = {}
context.update(extra_context or {})
- context.update({'page': self, 'attributes': self.attributes_with_node(node), 'relationships': self.relationships_with_node(node)})
+ context.update({'node': node, 'page': self, 'attributes': self.attributes_with_node(node), 'relationships': self.relationships_with_node(node)})
return HttpResponse(self.template.django_template.render(RequestContext(request, context)), mimetype=self.template.mimetype)
def __unicode__(self):
--- /dev/null
+from django import template
+from django.conf import settings
+from django.contrib.sites.models import Site
+
+
+register = template.Library()
+
+
+class NodeURLNode(template.Node):
+ def __init__(self, node, with_obj, as_var):
+ if node is not None:
+ self.node = template.Variable(node)
+ else:
+ self.node = None
+
+ if with_obj is not None:
+ self.with_obj = template.Variable(with_obj)
+ else:
+ self.with_obj = None
+
+ self.as_var = as_var
+
+ def render(self, context):
+ try:
+ if self.node:
+ node = self.node.resolve(context)
+ else:
+ node = context['node']
+ current_site = Site.objects.get_current()
+ if node.has_ancestor(current_site.root_node):
+ url = node.get_path(root=current_site.root_node)
+ if self.with_obj:
+ with_obj = self.with_obj.resolve(context)
+ url += node.view.get_subpath(with_obj)
+ else:
+ return settings.TEMPLATE_STRING_IF_INVALID
+
+ if self.as_var:
+ context[self.as_var] = url
+ return settings.TEMPLATE_STRING_IF_INVALID
+ else:
+ return url
+ except:
+ return settings.TEMPLATE_STRING_IF_INVALID
+
+
+@register.tag(name='node_url')
+def do_node_url(parser, token):
+ """
+ {% node_url [<node>] [with <obj>] [as <var>] %}
+ """
+ params = token.split_contents()
+ tag = params[0]
+
+ if len(params) <= 6:
+ node = None
+ with_obj = None
+ as_var = None
+ remaining_tokens = params[1:]
+ while remaining_tokens:
+ option_token = remaining_tokens.pop(0)
+ if option_token == 'with':
+ try:
+ with_obj = remaining_tokens.pop(0)
+ except IndexError:
+ raise template.TemplateSyntaxError('"%s" template tag option "with" requires an argument specifying an object handled by the view on the node' % tag)
+ elif option_token == 'as':
+ try:
+ as_var = remaining_tokens.pop(0)
+ except IndexError:
+ raise template.TemplateSyntaxError('"%s" template tag option "as" requires an argument specifying a variable name' % tag)
+ else: # node
+ node = option_token
+ return NodeURLNode(node=node, with_obj=with_obj, as_var=as_var)
+ else:
+ raise template.TemplateSyntaxError('"%s" template tag cannot accept more than five arguments' % tag)
\ No newline at end of file