class Meta:
model = Contentlet
- fields = ['name', 'content', 'dynamic']
+ fields = ['name', 'content']
class ContentReferenceForm(ContainerForm):
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:
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
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):
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)
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
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
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
'load',
'extends',
'include',
+ 'debug',
)
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)
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:
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):