Skip to content

Instantly share code, notes, and snippets.

@lsemel
Created May 22, 2011 20:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsemel/985854 to your computer and use it in GitHub Desktop.
Save lsemel/985854 to your computer and use it in GitHub Desktop.
Jinja2 capture extension, inspired by Rails content_for blocks
from jinja2 import nodes
from jinja2.ext import Extension
class CaptureExtension(Extension):
"""
Generic HTML capture, inspired by Rails' capture helper
In any template, you can capture an area of content and store it in a global
variable:
{% contentfor 'name_of_variable' %}
blah blah blah
{% endcontentfor %}
To display the result
{{ capture.name_of_variable }}
Multiple contentfor blocks will append additional content to any previously
captured content.
The context is global, and works within macros as well, so it's useful for letting macros define
javascript or <head> tag content that needs to go at a particular position
on the base template.
IMPORTANT: Make sure that whater function you use to render Jinja templates clears the 'capture' global each time it runs
or else you'll get captured content from previous renders
Inspired by http://stackoverflow.com/questions/4292630/insert-javascript-at-top-of-including-file-in-jinja-2
and http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html
"""
tags = set(['contentfor'])
def __init__(self, environment):
super(CaptureExtension, self).__init__(environment)
def parse(self, parser):
"""Parse tokens """
tag = parser.stream.next()
args = [parser.parse_expression()]
body = parser.parse_statements(['name:endcontentfor'], drop_needle=True)
return nodes.CallBlock(self.call_method('_capture', args),[], [], body).set_lineno(tag.lineno)
def _capture(self, name, caller):
if 'capture' not in self.environment.globals:
self.environment.globals['capture'] = {}
if name not in self.environment.globals['capture']:
self.environment.globals['capture'][name] = ''
self.environment.globals['capture'][name] += caller()
return ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment