X-Git-Url: http://git.ithinksw.org/philo.git/blobdiff_plain/fb8a270fa22abc217efc471d860c76d5a2352c61..17e82da27c3b2de8a6ab4b2e745122c1b3e541c6:/philo/templatetags/containers.py diff --git a/philo/templatetags/containers.py b/philo/templatetags/containers.py index c5fd445..c9ef2a0 100644 --- a/philo/templatetags/containers.py +++ b/philo/templatetags/containers.py @@ -1,13 +1,28 @@ +""" +The container template tags are automatically included as builtins if :mod:`philo` is an installed app. + +""" + from django import template from django.conf import settings -from django.utils.safestring import SafeUnicode, mark_safe -from django.core.exceptions import ObjectDoesNotExist from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Q +from django.utils.safestring import SafeUnicode, mark_safe register = template.Library() +CONTAINER_CONTEXT_KEY = 'philo_container_context' + + +class ContainerContext(object): + def __init__(self, contentlets, references): + self.contentlets = dict(((c.name, c) for c in contentlets)) + self.references = dict((((c.name, ContentType.objects.get_for_id(c.content_type_id)), c) for c in references)) + + class ContainerNode(template.Node): def __init__(self, name, references=None, as_var=None): self.name = name @@ -15,53 +30,57 @@ class ContainerNode(template.Node): self.references = references def render(self, context): - content = settings.TEMPLATE_STRING_IF_INVALID - if 'page' in context: - container_content = self.get_container_content(context) - else: - container_content = None + container_content = self.get_container_content(context) if self.as_var: context[self.as_var] = container_content return '' - if not container_content: - return '' - return container_content def get_container_content(self, context): - page = context['page'] + try: + container_context = context.render_context[CONTAINER_CONTEXT_KEY] + except KeyError: + try: + page = context['page'] + except KeyError: + return settings.TEMPLATE_STRING_IF_INVALID + + contentlets = page.contentlets.all() + references = page.contentreferences.all() + + container_context = ContainerContext(contentlets, references) + context.render_context[CONTAINER_CONTEXT_KEY] = container_context + if self.references: # Then it's a content reference. try: - contentreference = page.contentreferences.get(name__exact=self.name, content_type=self.references) - content = contentreference.content - except ObjectDoesNotExist: + contentreference = container_context.references[(self.name, self.references)] + except KeyError: content = '' + else: + content = contentreference.content else: # Otherwise it's a contentlet. try: - contentlet = page.contentlets.get(name__exact=self.name) - if '{%' in contentlet.content or '{{' in contentlet.content: - try: - content = template.Template(contentlet.content, name=contentlet.name).render(context) - except template.TemplateSyntaxError, error: - if settings.DEBUG: - content = ('[Error parsing contentlet \'%s\': %s]' % (self.name, error)) - else: - content = settings.TEMPLATE_STRING_IF_INVALID - else: - content = contentlet.content - except ObjectDoesNotExist: - content = settings.TEMPLATE_STRING_IF_INVALID - content = mark_safe(content) + contentlet = container_context.contentlets[self.name] + except KeyError: + content = '' + else: + content = contentlet.content return content -def do_container(parser, token): +@register.tag +def container(parser, token): """ - {% container [[references ] as ] %} + If a template using this tag is used to render a :class:`.Page`, that :class:`.Page` will have associated content which can be set in the admin interface. If a content type is referenced, then a :class:`.ContentReference` object will be created; otherwise, a :class:`.Contentlet` object will be created. + + Usage:: + + {% container [[references .] as ] %} + """ params = token.split_contents() if len(params) >= 2: @@ -76,7 +95,7 @@ def do_container(parser, token): if option_token == 'references': try: app_label, model = remaining_tokens.pop(0).strip('"').split('.') - references = ContentType.objects.get(app_label=app_label, model=model) + references = ContentType.objects.get_by_natural_key(app_label, model) except IndexError: raise template.TemplateSyntaxError('"%s" template tag option "references" requires an argument specifying a content type' % tag) except ValueError: @@ -94,6 +113,3 @@ def do_container(parser, token): else: # error raise template.TemplateSyntaxError('"%s" template tag provided without arguments (at least one required)' % tag) - - -register.tag('container', do_container)