From: Stephen Burrows Date: Fri, 1 Oct 2010 14:24:02 +0000 (-0400) Subject: Removed 'dynamic' from the Contentlet model. Added TemplateField to Template model... X-Git-Tag: philo-0.9~30^2~4 X-Git-Url: http://git.ithinksw.org/philo.git/commitdiff_plain/24677328851cc04e6b15254606dfadd8af8a2432 Removed 'dynamic' from the Contentlet model. Added TemplateField to Template model and Contentlet model. Fixed some minor typos and added some comments to the code. Increased verbosity of 'disallowed tag' errors. --- diff --git a/forms.py b/forms.py index bf498fa..3c6ed1a 100644 --- a/forms.py +++ b/forms.py @@ -141,7 +141,7 @@ class ContentletForm(ContainerForm): class Meta: model = Contentlet - fields = ['name', 'content', 'dynamic'] + fields = ['name', 'content'] class ContentReferenceForm(ContainerForm): diff --git a/models/fields.py b/models/fields.py index 79b31b3..dbf1886 100644 --- a/models/fields.py +++ b/models/fields.py @@ -147,9 +147,9 @@ class RelationshipField(EntityProxyField): class TemplateField(models.TextField): - def __init__(self, allow=None, disallow=None, *args, **kwargs): + def __init__(self, allow=None, disallow=None, secure=True, *args, **kwargs): super(TemplateField, self).__init__(*args, **kwargs) - self.validators.append(TemplateValidator(allow, disallow)) + self.validators.append(TemplateValidator(allow, disallow, secure)) try: diff --git a/models/pages.py b/models/pages.py index 45ffe64..daeb621 100644 --- a/models/pages.py +++ b/models/pages.py @@ -11,6 +11,7 @@ from django.template.loader import get_template from django.template.loader_tags import ExtendsNode, ConstantIncludeNode from django.http import HttpResponse from philo.models.base import TreeModel, register_value_model +from philo.models.fields import TemplateField from philo.models.nodes import View from philo.utils import fattr from philo.templatetags.containers import ContainerNode @@ -38,7 +39,7 @@ class Template(TreeModel): name = models.CharField(max_length=255) documentation = models.TextField(null=True, blank=True) mimetype = models.CharField(max_length=255, default=getattr(settings, 'DEFAULT_CONTENT_TYPE', 'text/html')) - code = models.TextField(verbose_name='django template code') + code = TemplateField(secure=False, verbose_name='django template code') @property def origin(self): @@ -66,10 +67,13 @@ class Template(TreeModel): if hasattr(node, nodelist_name): nodes.extend(nodelist_container_nodes(getattr(node, nodelist_name))) - # _philo_additional_template is a property philo provides on all nodes that require it - # and which it monkeypatches onto the relevant default nodes. - if hasattr(node, LOADED_TEMPLATE_ATTR) and getattr(node, LOADED_TEMPLATE_ATTR): - nodes.extend(container_nodes(LOADED_TEMPLATE_ATTR)) + # LOADED_TEMPLATE_ATTR contains the name of an attribute philo uses to declare a + # node as rendering an additional template. Philo monkeypatches the attribute onto + # the relevant default nodes. + if hasattr(node, LOADED_TEMPLATE_ATTR): + loaded_template = getattr(node, LOADED_TEMPLATE_ATTR) + if loaded_template: + nodes.extend(container_nodes(loaded_template)) if isinstance(node, ContainerNode): nodes.append(node) @@ -143,8 +147,7 @@ class Page(View): class Contentlet(models.Model): page = models.ForeignKey(Page, related_name='contentlets') name = models.CharField(max_length=255) - content = models.TextField() - dynamic = models.BooleanField(default=False) + content = TemplateField() def __unicode__(self): return self.name diff --git a/templatetags/containers.py b/templatetags/containers.py index 90af297..8bb0c6b 100644 --- a/templatetags/containers.py +++ b/templatetags/containers.py @@ -33,24 +33,29 @@ class ContainerNode(template.Node): def get_container_content(self, context): page = context['page'] 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: content = '' else: + # Otherwise it's a contentlet. try: contentlet = page.contentlets.get(name__exact=self.name) - if contentlet.dynamic: + if '{%' in contentlet.content: try: - content = mark_safe(template.Template(contentlet.content, name=contentlet.name).render(context)) + 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 = '' + content = settings.TEMPLATE_STRING_IF_INVALID + content = mark_safe(content) return content diff --git a/validators.py b/validators.py index 106db8b..5f69f74 100644 --- a/validators.py +++ b/validators.py @@ -1,6 +1,7 @@ from django.utils.translation import ugettext_lazy as _ from django.core.validators import RegexValidator from django.core.exceptions import ValidationError +from django.template import Template, Parser, Lexer, TOKEN_BLOCK, TOKEN_VAR from django.utils import simplejson as json import re @@ -10,6 +11,7 @@ INSECURE_TAGS = ( 'load', 'extends', 'include', + 'debug', ) @@ -47,9 +49,6 @@ def json_validator(value): raise ValidationError(u'\'%s\' is not valid JSON' % value) -from django.template import Template, Parser, Lexer, TOKEN_BLOCK - - class TemplateValidationParser(Parser): def __init__(self, tokens, allow=None, disallow=None, secure=True): super(TemplateValidationParser, self).__init__(tokens) @@ -59,7 +58,7 @@ class TemplateValidationParser(Parser): if secure: disallow |= set(INSECURE_TAGS) - self.allow, self.disallow = allow, disallow + self.allow, self.disallow, self.secure = allow, disallow, secure def parse(self, parse_until=None): if parse_until is None: @@ -112,7 +111,9 @@ class TemplateValidationParser(Parser): return nodelist def disallowed_tag(self, command): - raise ValidationError("Tag not allowed: %s" % command) + if self.secure and command in INSECURE_TAGS: + raise ValidationError('Tag "%s" is not permitted for security reasons.' % command) + raise ValidationError('Tag "%s" is not permitted here.' % command) class TemplateValidator(object):