Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proof of concept: Support for Django cached template loader. #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions djedi/loaders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django.template.loaders.cached import Loader
from .templatetags.djedi_tags import DjediNode


class DjediRefresherMixin(object):
"""
This mixin automatically refreshes each Djedi node for every
loaded template. Comes very handy in combination with caching template
loaders (ie `django.template.loaders.cached.Loader`).
"""
def load_template(self, template_name, template_dirs=None):
template, origin = super(DjediRefresherMixin, self).load_template(
template_name, template_dirs)
djedi_nodes = template.nodelist.get_nodes_by_type(DjediNode)
map(lambda n: n.reload_node(), djedi_nodes)
return template, origin


class DjediCachedLoader(DjediRefresherMixin, Loader):
"""
Standard Django cached template loader with support for Djedi nodes.
"""
pass
58 changes: 38 additions & 20 deletions djedi/templatetags/djedi_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,48 @@ def render_node(node, context=None, edit=True):
return output


@register.lazy_tag
def node(key, default=None, edit=True):
class DjediNode(template.Node):
def __init__(self, uri, default, kwargs):
self.uri = uri
self.default = default
self.reload_node()
self.kwargs = kwargs

def reload_node(self):
self.node = cio.get(self.uri, self.default or u'')

def render(self, context):
# Resolve tag kwargs against context
resolved_kwargs = dict((key, value.resolve(context)) for key, value in self.kwargs.iteritems())
edit = resolved_kwargs.pop('edit', True)

return render_node(self.node, context=resolved_kwargs, edit=edit)


class SimpleNode(DjediNode):
"""
Simple node tag:
{% node 'page/title' default='Lorem ipsum' edit=True %}
"""
node = cio.get(key, default=default or u'')
return lambda _: render_node(node, edit=edit)
@classmethod
def tag(cls, parser, token):
# Parse tag args and kwargs
bits = token.split_contents()[1:]
params = ('uri', 'edit', 'default')
args, kwargs = parse_bits(parser, bits, params, None, True, ('', True,), None, 'node')

# Assert uri is the only tag arg
if len(args) > 1:
raise TemplateSyntaxError('Malformed arguments to blocknode tag')

# Resolve uri variable
uri = args[0].resolve({})
default = kwargs['default'].resolve({}) if 'default' in kwargs else u''

return cls(uri, default, kwargs)

class BlockNode(template.Node):

class BlockNode(DjediNode):
"""
Block node tag using body content as default:
{% blocknode 'page/title' edit=True %}
Expand Down Expand Up @@ -57,21 +88,8 @@ def tag(cls, parser, token):
default = default.strip('\n\r')
default = textwrap.dedent(default)

# Get node for uri, lacks context variable lookup due to lazy loading.
node = cio.get(uri, default)

return cls(tokens, node, kwargs)
return cls(uri, default, kwargs)

def __init__(self, tokens, node, kwargs):
self.tokens = tokens
self.node = node
self.kwargs = kwargs

def render(self, context):
# Resolve tag kwargs against context
resolved_kwargs = dict((key, value.resolve(context)) for key, value in self.kwargs.iteritems())
edit = resolved_kwargs.pop('edit', True)

return render_node(self.node, context=resolved_kwargs, edit=edit)

register.tag('node', SimpleNode.tag)
register.tag('blocknode', BlockNode.tag)