Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 144 lines (116 sloc) 4.707 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
52098e1 @DasIch Happy New Year 2014
DasIch authored
8 :copyright: (c) 2014 by Armin Ronacher.
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
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
f34c028 @mitsuhiko Added template tests and made config a true global
authored
15 from .globals import _request_ctx_stack, _app_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
a080171 @DasIch Remove six dependency
DasIch authored
18 from ._compat import itervalues, iteritems
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
19
20
665fa2a @mitsuhiko More refactoring and moving stuff around
authored
21 def _default_template_ctx_processor():
22 """Default template context processor. Injects `request`,
23 `session` and `g`.
24 """
25 reqctx = _request_ctx_stack.top
1949c4a @mitsuhiko flask.g is now on the app context and not the request context
authored
26 appctx = _app_ctx_stack.top
27 rv = {}
28 if appctx is not None:
29 rv['g'] = appctx.g
30 if reqctx is not None:
31 rv['request'] = reqctx.request
32 rv['session'] = reqctx.session
33 return rv
665fa2a @mitsuhiko More refactoring and moving stuff around
authored
34
35
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
36 class Environment(BaseEnvironment):
37 """Works like a regular Jinja2 environment but has some additional
38 knowledge of how Flask's blueprint works so that it can prepend the
39 name of the blueprint to referenced templates if necessary.
40 """
41
42 def __init__(self, app, **options):
43 if 'loader' not in options:
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
44 options['loader'] = app.create_global_jinja_loader()
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
45 BaseEnvironment.__init__(self, **options)
46 self.app = app
47
48
49 class DispatchingJinjaLoader(BaseLoader):
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
50 """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.…
authored
51 the blueprint folders.
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
52 """
53
54 def __init__(self, app):
55 self.app = app
56
57 def get_source(self, environment, template):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
58 for loader, local_name in self._iter_loaders(template):
59 try:
60 return loader.get_source(environment, local_name)
61 except TemplateNotFound:
62 pass
63
64 raise TemplateNotFound(template)
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
65
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
66 def _iter_loaders(self, template):
67 loader = self.app.jinja_loader
68 if loader is not None:
69 yield loader, template
70
71 # old style module based loaders in case we are dealing with a
72 # blueprint that is an old style module
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
73 try:
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
74 module, local_name = posixpath.normpath(template).split('/', 1)
7a08331 @mitsuhiko Latest iteration of the blueprint code. Far from being done
authored
75 blueprint = self.app.blueprints[module]
76 if blueprint_is_module(blueprint):
77 loader = blueprint.jinja_loader
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
78 if loader is not None:
79 yield loader, local_name
80 except (ValueError, KeyError):
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
81 pass
82
a080171 @DasIch Remove six dependency
DasIch authored
83 for blueprint in itervalues(self.app.blueprints):
c9a2ad2 @mitsuhiko Fixed a bug in list_templates
authored
84 if blueprint_is_module(blueprint):
85 continue
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
86 loader = blueprint.jinja_loader
87 if loader is not None:
88 yield loader, template
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
89
90 def list_templates(self):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
91 result = set()
92 loader = self.app.jinja_loader
93 if loader is not None:
94 result.update(loader.list_templates())
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
95
a080171 @DasIch Remove six dependency
DasIch authored
96 for name, blueprint in iteritems(self.app.blueprints):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
97 loader = blueprint.jinja_loader
98 if loader is not None:
99 for template in loader.list_templates():
100 prefix = ''
c9a2ad2 @mitsuhiko Fixed a bug in list_templates
authored
101 if blueprint_is_module(blueprint):
abe1378 @mitsuhiko Chnaged a bunch of behavior in blueprints for it to be more flexible.…
authored
102 prefix = name + '/'
103 result.add(prefix + template)
a06cd0a @mitsuhiko Started work on implementing blueprint based template loading
authored
104
105 return list(result)
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
106
107
e0712b4 @mitsuhiko Added support for signals
authored
108 def _render(template, context, app):
109 """Renders the template and fires the signal"""
110 rv = template.render(context)
111 template_rendered.send(app, template=template, context=context)
112 return rv
113
114
0b33693 @dmishe Allow loading template from iterable
dmishe authored
115 def render_template(template_name_or_list, **context):
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
116 """Renders a template from the template folder with the given
117 context.
118
0b33693 @dmishe Allow loading template from iterable
dmishe authored
119 :param template_name_or_list: the name of the template to be
120 rendered, or an iterable with template names
121 the first one existing will be rendered
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
122 :param context: the variables that should be available in the
123 context of the template.
124 """
f34c028 @mitsuhiko Added template tests and made config a true global
authored
125 ctx = _app_ctx_stack.top
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
126 ctx.app.update_template_context(context)
0b33693 @dmishe Allow loading template from iterable
dmishe authored
127 return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
e0712b4 @mitsuhiko Added support for signals
authored
128 context, ctx.app)
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
129
130
131 def render_template_string(source, **context):
132 """Renders a template from the given template source string
133 with the given context.
134
9ecbd20 @ralphbean Update flask/templating.py
ralphbean authored
135 :param source: the sourcecode of the template to be
136 rendered
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
137 :param context: the variables that should be available in the
138 context of the template.
139 """
f34c028 @mitsuhiko Added template tests and made config a true global
authored
140 ctx = _app_ctx_stack.top
a3c9494 @mitsuhiko Moved templating stuff into a separate module
authored
141 ctx.app.update_template_context(context)
e0712b4 @mitsuhiko Added support for signals
authored
142 return _render(ctx.app.jinja_env.from_string(source),
143 context, ctx.app)
Something went wrong with that request. Please try again.