Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 139 lines (111 sloc) 4.417 kb
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
1 # -*- coding: utf-8 -*-
2 """
3 flask.templating
4 ~~~~~~~~~~~~~~~~
5
6 Implements the bridge to Jinja2.
7
8 :copyright: (c) 2010 by Armin Ronacher.
9 :license: BSD, see LICENSE for more details.
10 """
a3a8439 @mitsuhiko normpath is now used before loading templates
authored
11 import posixpath
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
12 from jinja2 import BaseLoader, Environment as BaseEnvironment, \
13 TemplateNotFound
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
14
80eb6cf @mitsuhiko Switched to relative imports in the package
authored
15 from .globals import _request_ctx_stack
e0712b4 @mitsuhiko Added support for signals
authored
16 from .signals import template_rendered
7a08331 @mitsuhiko Latest iteration of the blueprint code. Far from being done
authored
17 from .module import blueprint_is_module
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
18
19
665fa2a @mitsuhiko More refactoring and moving stuff around
authored
20 def _default_template_ctx_processor():
21 """Default template context processor. Injects `request`,
22 `session` and `g`.
23 """
24 reqctx = _request_ctx_stack.top
25 return dict(
aa3d839 @mitsuhiko Config is now available in templates, context processors no longer overr...
authored
26 config=reqctx.app.config,
665fa2a @mitsuhiko More refactoring and moving stuff around
authored
27 request=reqctx.request,
28 session=reqctx.session,
29 g=reqctx.g
30 )
31
32
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
33 class Environment(BaseEnvironment):
34 """Works like a regular Jinja2 environment but has some additional
35 knowledge of how Flask's blueprint works so that it can prepend the
36 name of the blueprint to referenced templates if necessary.
37 """
38
39 def __init__(self, app, **options):
40 if 'loader' not in options:
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
41 options['loader'] = app.create_global_jinja_loader()
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
42 BaseEnvironment.__init__(self, **options)
43 self.app = app
44
45
46 class DispatchingJinjaLoader(BaseLoader):
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
47 """A loader that looks for templates in the application and all
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
48 the blueprint folders.
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
49 """
50
51 def __init__(self, app):
52 self.app = app
53
54 def get_source(self, environment, template):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
55 for loader, local_name in self._iter_loaders(template):
56 try:
57 return loader.get_source(environment, local_name)
58 except TemplateNotFound:
59 pass
60
61 raise TemplateNotFound(template)
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
62
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
63 def _iter_loaders(self, template):
64 loader = self.app.jinja_loader
65 if loader is not None:
66 yield loader, template
67
68 # old style module based loaders in case we are dealing with a
69 # blueprint that is an old style module
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
70 try:
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
71 module, local_name = posixpath.normpath(template).split('/', 1)
7a08331 @mitsuhiko Latest iteration of the blueprint code. Far from being done
authored
72 blueprint = self.app.blueprints[module]
73 if blueprint_is_module(blueprint):
74 loader = blueprint.jinja_loader
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
75 if loader is not None:
76 yield loader, local_name
77 except (ValueError, KeyError):
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
78 pass
79
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
80 for blueprint in self.app.blueprints.itervalues():
3716e77 @mitsuhiko Fixed a bug in list_templates
authored
81 if blueprint_is_module(blueprint):
82 continue
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
83 loader = blueprint.jinja_loader
84 if loader is not None:
85 yield loader, template
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
86
87 def list_templates(self):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
88 result = set()
89 loader = self.app.jinja_loader
90 if loader is not None:
91 result.update(loader.list_templates())
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
92
93 for name, blueprint in self.app.blueprints.iteritems():
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
94 loader = blueprint.jinja_loader
95 if loader is not None:
96 for template in loader.list_templates():
97 prefix = ''
3716e77 @mitsuhiko Fixed a bug in list_templates
authored
98 if blueprint_is_module(blueprint):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible. Im...
authored
99 prefix = name + '/'
100 result.add(prefix + template)
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
101
102 return list(result)
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
103
104
e0712b4 @mitsuhiko Added support for signals
authored
105 def _render(template, context, app):
106 """Renders the template and fires the signal"""
107 rv = template.render(context)
108 template_rendered.send(app, template=template, context=context)
109 return rv
110
111
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
112 def render_template(template_name, **context):
113 """Renders a template from the template folder with the given
114 context.
115
116 :param template_name: the name of the template to be rendered
117 :param context: the variables that should be available in the
118 context of the template.
119 """
120 ctx = _request_ctx_stack.top
121 ctx.app.update_template_context(context)
e0712b4 @mitsuhiko Added support for signals
authored
122 return _render(ctx.app.jinja_env.get_template(template_name),
123 context, ctx.app)
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
124
125
126 def render_template_string(source, **context):
127 """Renders a template from the given template source string
128 with the given context.
129
130 :param template_name: the sourcecode of the template to be
131 rendered
132 :param context: the variables that should be available in the
133 context of the template.
134 """
135 ctx = _request_ctx_stack.top
136 ctx.app.update_template_context(context)
e0712b4 @mitsuhiko Added support for signals
authored
137 return _render(ctx.app.jinja_env.from_string(source),
138 context, ctx.app)
Something went wrong with that request. Please try again.