testdata tag for templates

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{% 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)

More like this

  1. Repeat blocks with new context / simple Jinja-like macro system by miracle2k 6 years, 8 months ago
  2. outliner template tag by showell 4 years, 12 months ago
  3. Paginator TemplateTag by trbs 6 years ago
  4. Markdown and Syntax Highlighting in Django by blinks 7 years, 1 month ago
  5. Showell markup--DRY up your templates by showell 4 years, 4 months ago

Comments

(Forgotten your password?)