1 | #!/usr/bin/env python
|
---|
2 |
|
---|
3 | import sys, os
|
---|
4 | from datetime import datetime, timedelta
|
---|
5 |
|
---|
6 | sys.path.append("../")
|
---|
7 | sys.path.append(".")
|
---|
8 |
|
---|
9 | os.environ[ "DJANGO_SETTINGS_MODULE" ] = "settings"
|
---|
10 |
|
---|
11 | from django.template import loader, Context
|
---|
12 | from timeit import Timer
|
---|
13 | from django.template.loader_tags import *
|
---|
14 | from django import template
|
---|
15 |
|
---|
16 | register = Library()
|
---|
17 |
|
---|
18 | class ExtendsNode(Node):
|
---|
19 | must_be_first = True
|
---|
20 |
|
---|
21 | def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None):
|
---|
22 | self.nodelist = nodelist
|
---|
23 | self.parent_name, self.parent_name_expr = parent_name, parent_name_expr
|
---|
24 | self.template_dirs = template_dirs
|
---|
25 | self.compiled_parent = None
|
---|
26 |
|
---|
27 | def __repr__(self):
|
---|
28 | if self.parent_name_expr:
|
---|
29 | return "<ExtendsNode: extends %s>" % self.parent_name_expr.token
|
---|
30 | return '<ExtendsNode: extends "%s">' % self.parent_name
|
---|
31 |
|
---|
32 | def get_parent(self, context):
|
---|
33 | if self.parent_name_expr:
|
---|
34 | self.parent_name = self.parent_name_expr.resolve(context)
|
---|
35 | parent = self.parent_name
|
---|
36 | if not parent:
|
---|
37 | error_msg = "Invalid template name in 'extends' tag: %r." % parent
|
---|
38 | if self.parent_name_expr:
|
---|
39 | error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token
|
---|
40 | raise TemplateSyntaxError, error_msg
|
---|
41 | if hasattr(parent, 'render'):
|
---|
42 | return parent # parent is a Template object
|
---|
43 | try:
|
---|
44 | source, origin = find_template_source(parent, self.template_dirs)
|
---|
45 | except TemplateDoesNotExist:
|
---|
46 | raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent
|
---|
47 | else:
|
---|
48 | return get_template_from_string(source, origin, parent)
|
---|
49 |
|
---|
50 | def process_parent( self, context ):
|
---|
51 | compiled_parent = self.get_parent(context)
|
---|
52 | pos = 0
|
---|
53 | while isinstance(compiled_parent.nodelist[pos], TextNode):
|
---|
54 | pos += 1
|
---|
55 | parent_is_child = isinstance(compiled_parent.nodelist[pos], ExtendsNode)
|
---|
56 | parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
|
---|
57 | for block_node in self.nodelist.get_nodes_by_type(BlockNode):
|
---|
58 | try:
|
---|
59 | parent_block = parent_blocks[block_node.name]
|
---|
60 | except KeyError:
|
---|
61 | if parent_is_child:
|
---|
62 | compiled_parent.nodelist[pos].nodelist.append(block_node)
|
---|
63 | else:
|
---|
64 | parent_block.parent = block_node.parent
|
---|
65 | parent_block.add_parent(parent_block.nodelist)
|
---|
66 | parent_block.nodelist = block_node.nodelist
|
---|
67 | return compiled_parent
|
---|
68 |
|
---|
69 | def render(self, context):
|
---|
70 | if self.compiled_parent:
|
---|
71 | compiled_parent = self.compiled_parent
|
---|
72 | else:
|
---|
73 | compiled_parent = self.process_parent(context)
|
---|
74 | # cache it, if static
|
---|
75 | if self.parent_name:
|
---|
76 | self.compiled_parent = compiled_parent
|
---|
77 |
|
---|
78 | return compiled_parent.render(context)
|
---|
79 |
|
---|
80 |
|
---|
81 | @register.tag
|
---|
82 | def extends(parser, token):
|
---|
83 | bits = token.contents.split()
|
---|
84 | if len(bits) != 2:
|
---|
85 | raise TemplateSyntaxError, "'%s' takes one argument" % bits[0]
|
---|
86 | parent_name, parent_name_expr = None, None
|
---|
87 | if bits[1][0] in ('"', "'") and bits[1][-1] == bits[1][0]:
|
---|
88 | parent_name = bits[1][1:-1]
|
---|
89 | else:
|
---|
90 | parent_name_expr = parser.compile_filter(bits[1])
|
---|
91 | nodelist = parser.parse()
|
---|
92 | if nodelist.get_nodes_by_type(ExtendsNode):
|
---|
93 | raise TemplateSyntaxError, "'%s' cannot appear more than once in the same template" % bits[0]
|
---|
94 | return ExtendsNode(nodelist, parent_name, parent_name_expr)
|
---|
95 |
|
---|
96 |
|
---|
97 | t = loader.get_template('registration/password_reset_done.html')
|
---|
98 |
|
---|
99 | def x():
|
---|
100 | return t.render( Context() )
|
---|
101 |
|
---|
102 | def test():
|
---|
103 | timer = Timer("x()", "from __main__ import x")
|
---|
104 | print "time: %s" % (timer.timeit(1000) )
|
---|
105 |
|
---|
106 | test()
|
---|
107 |
|
---|
108 | # turn on modified tag, and reload variable t
|
---|
109 | template.builtins.append( register )
|
---|
110 | t = loader.get_template('registration/password_reset_done.html')
|
---|
111 |
|
---|
112 | test()
|
---|