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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
.. aiohttp_jinja2 documentation master file, created by
sphinx-quickstart on Sun Mar 22 12:04:15 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
aiohttp_jinja2
==============
.. currentmodule:: aiohttp_jinja2
.. highlight:: python
:term:`jinja2` template renderer for :ref:`aiohttp.web<aiohttp-web>`.
Usage
-----
Before template rendering you have to setup *jinja2 environment*
(:class:`jinja2.Environment`) first::
app = web.Application()
aiohttp_jinja2.setup(app,
loader=jinja2.FileSystemLoader('/path/to/templates/folder'))
After that you may use template engine in your
:term:`web-handlers<web-handler>`. The most convenient way is to
decorate a :term:`web-handler`.
Using the function based web handlers::
@aiohttp_jinja2.template('tmpl.jinja2')
def handler(request):
return {'name': 'Andrew', 'surname': 'Svetlov'}
Or the class-based views (:class:`aiohttp.web.View`)::
class Handler(web.View):
@aiohttp_jinja2.template('tmpl.jinja2')
async def get(self):
return {'name': 'Andrew', 'surname': 'Svetlov'}
On handler call the :func:`template` decorator will pass
returned dictionary ``{'name': 'Andrew', 'surname': 'Svetlov'}`` into
template named ``"tmpl.jinja2"`` for getting resulting HTML text.
More complex template processing can be achieved by modifying the existing
`list of global functions <http://jinja.pocoo.org/docs/2.10/templates/#builtin-globals>`_.
Modification of Jinja2's environment can be done via :func:`get_env`.
For example, adding the ``zip`` function::
env = aiohttp_jinja2.get_env(app)
env.globals.update(zip=zip)
Which can now to be used in any template::
{% for value, square in zip(values, squares) %}
<p>The square of {{ value }} is {{ square }}.</p>
{% endfor %}
In some cases, finer control over the dataflow may also be required.
This can be worked out by explicitly asking for template to be rendered
using :func:`render_template`.
Explicit rendering will allow to possibly
pass some context to the renderer
and also to modify its response on the fly.
This can for example be used to set response headers::
async def handler(request):
context = {'name': 'Andrew', 'surname': 'Svetlov'}
response = aiohttp_jinja2.render_template('tmpl.jinja2',
request,
context)
response.headers['Content-Language'] = 'ru'
return response
This, again, can also be done with a class-based view (:class:`aiohttp.web.View`)::
class Handler(web.View):
async def get(self):
context = {'name': 'Andrew', 'surname': 'Svetlov'}
response = aiohttp_jinja2.render_template('tmpl.jinja2',
self.request,
context)
response.headers['Content-Language'] = 'ru'
return response
Context processors is a way to add some variables to each
template context. It works like :attr:`jinja2.Environment().globals`,
but calculate variables each request. So if you need to
add global constants it will be better to use
:attr:`jinja2.Environment().globals` directly. But if you variables depends of
request (e.g. current user) you have to use context processors.
Context processors is following last-win strategy.
Therefore a context processor could rewrite variables delivered with
previous one.
In order to use context processors create required processors::
async def foo_processor(request):
return {'foo': 'bar'}
And pass them into :func:`setup`::
aiohttp_jinja2.setup(
app,
context_processors=[foo_processor,
aiohttp_jinja2.request_processor],
loader=loader)
As you can see, there is a built-in :func:`request_processor`, which
adds current :class:`aiohttp.web.Request` into context of templates
under ``'request'`` name.
Here is an example of how to add current user dependant logic
to template (requires ``aiohttp_security`` library)::
from aiohttp_security import authorized_userid
async def current_user_ctx_processor(request):
userid = await authorized_userid(request)
is_anonymous = not bool(userid)
return {'current_user': {'is_anonymous': is_anonymous}}
Template::
<body>
<div>
{% if current_user.is_anonymous %}
<a href="{{ url('login') }}">Login</a>
{% else %}
<a href="{{ url('logout') }}">Logout</a>
{% endif %}
</div>
</body>
Async functions
...............
If you pass the ``enable_async`` parameter to the setup function, then you
will need to use the async functions for rendering::
aiohttp_jinja2.setup(
app, enable_async=True,
loader=jinja2.FileSystemLoader('/path/to/templates/folder'))
...
async def handler(request):
return await aiohttp_jinja2.render_template_async(
'tmpl.jinja2', request)
The ``@aiohttp_jinja2.template`` decorator will work for both cases.
Default Globals
...............
.. highlight:: html+jinja
``app`` is always made in templates via :attr:`jinja2.Environment().globals`::
<body>
<h1>Welcome to {{ app['name'] }}</h1>
</body>
Two more helpers are also enabled by default: ``url`` and ``static``.
``url`` can be used with just a view name::
<body>
<a href="{{ url('index') }}">Index Page</a>
</body>
Or with arguments::
<body>
<a href="{{ url('user', id=123) }}">User Page</a>
</body>
A query can be added to the url with the special ``query_`` keyword argument::
<body>
<a href="{{ url('user', id=123, query_={'foo': 'bar'}) }}">User Page</a>
</body>
For a view defined by ``app.router.add_get('/user-profile/{id}/',
user, name='user')``, the above would give::
<body>
<a href="/user-profile/123/?foo=bar">User Page</a>
</body>
This is useful as it would allow your static path to switch in
deployment or testing with just one line.
The ``static`` function has similar usage, except it requires you to
set ``app[aiohttp_jinja2.static_root_key]``.
.. code-block:: python
app = web.Application()
aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader("/path/to/templates/folder"))
app[aiohttp_jinja2.static_root_key] = "/static"
Then in the template::
<script src="{{ static('dist/main.js') }}"></script>
Would result in::
<script src="/static/dist/main.js"></script>
Both ``url`` and ``static`` can be disabled by passing
``default_helpers=False`` to ``aiohttp_jinja2.setup``.
Library Installation
--------------------
The :mod:`aiohttp_jinja2` can be installed by pip::
$ pip3 install aiohttp_jinja2
Source code
-----------
The project is hosted on `GitHub <https://github.com/aio-libs/aiohttp_jinja2>`_.
Please feel free to file an issue on `bug tracker
<https://github.com/aio-libs/aiohttp_jinja2/issues>`_ if you have found a bug
or have some suggestion for library improvement.
The library uses `Travis <https://travis-ci.org/aio-libs/aiohttp-jinja2>`_ for
Continuous Integration.
License
-------
:mod:`aiohttp_jinja2` is offered under the Apache 2 license.
Contents
--------
.. toctree::
:maxdepth: 2
api
Indices and tables
------------------
* :ref:`genindex`
* :ref:`search`
Glossary
--------
.. if you add new entries, keep the alphabetical sorting!
.. glossary::
jinja2
A modern and designer-friendly templating language for Python.
See http://jinja.pocoo.org/
web-handler
An endpoint that returns http response.
|