{% load handytags %}
Example code for testdata tag
<hr />
{% testdata %}
	{% if earth %}
		{
	    	'greeting': 'Hello',
	    	'planet': 'World',
		}
	{% endif %}
	{% if mars %}
		{
	    	'greeting': 'Aloha',
	    	'planet': 'Mars',
		}
	{% endif %}
{% --- %}
	{# This is where the actual template begins #}
	{{ greeting }} <b>{{ planet }}</b>
{% endtestdata %}

################

class VerboseContext(object):
    # We proxy the context to allow us to 
    # intercept things that it quiets down.
    def __init__(self, dict, context):
        self.dict = dict
        self.context = context
        self.autoescape = context.autoescape

    def push(self): return self.context.push()
    def pop(self): return self.context.pop()

    def __setitem__(self, key, value):
        self.context[key] = value
        
    def __getitem__(self, key):
        if key in self.dict:
            value = self.dict[key]
        elif key in self.context:
            value = self.context[key]
        else:
            raise TemplateSyntaxError('%s NOT FOUND' % key)
        return value
    
    def __contains__(self, key):
        if key not in ['forloop',]:
            return True # so we can complain later
        return key in self.context
    
class TestDataNode(Node):
    def __init__(self, nodelist, data_nodelist):
        self.nodelist = nodelist
        self.data_nodelist = data_nodelist
    
    def render(self, context):
        if 'testdata_use' in context and context['testdata_use']:
            rendered_text = ''
            # We are treating data as a template,
            # mostly to allow includes to work, but people
            # can be creative.
            data_text = self.data_nodelist.render(context).strip()
            if not data_text:
                raise TemplateSyntaxError, "no data provided for testdata tag"
            raw_data = eval(data_text)
            proxy_context = VerboseContext(raw_data, context)
            rendered_text += self.nodelist.render(proxy_context)
            return rendered_text    
        else:
            # From normal code paths we just render the inner stuff
            # with the existing context.
            return self.nodelist.render(context)

@register.tag
def testdata(parser, token):
    bits = token.split_contents()
    if len(bits) != 1:
        raise TemplateSyntaxError, "%r tag takes no parameters" % bits[0]
    data_nodelist = parser.parse(('---',))
    parser.delete_first_token()
    nodelist = parser.parse(('endtestdata',))
    parser.delete_first_token()
    return TestDataNode(nodelist, data_nodelist)