I'm using Jinja2 templates with Bottle.py and Google App Engine's dev_appserver for development. I want the templates to automatically reload on every request (or ideally only when they change), so that I don't have to keep restarting the server.
According to bottle's docs, you're supposed to be able to disable template caching by calling bottle.debug(True)
.
Jinja still seems to be caching its templates, though. I believe this to be because of the way the bottle jinja2 adapter is written (it just uses a default Jinja2 loader and doesn't expose many configuration options).
Following the Jinja2 Docs, I wrote this custom Loader that I would expect to trigger a template reload every time, but it doesn't seem to work either:
import settings
from bottle import jinja2_template
from bottle import Jinja2Template, template as base_template
class AutoreloadJinja2Template(Jinja2Template):
def loader(self, name):
def uptodate():
# Always reload the template if we're in DEVMODE (a boolean flag)
return not settings.DEVMODE
fname = self.search(name, self.lookup)
if fname:
with open(fname, "rb") as f:
source = f.read().decode(self.encoding)
return (source, fname, uptodate)
template = functools.partial(base_template,
template_adapter=AutoreloadJinja2Template,
template_lookup = settings.TEMPLATE_PATHS,
template_settings={
'auto_reload': settings.DEVMODE
}
)
Templates are still getting cached until I restart dev_appserver. This must be a fairly common problem. Does anyone have a solution that works?
UPDATE:
I ended up doing something like:
class CustomJinja2Template(Jinja2Template):
if settings.DEVMODE:
def prepare(self, *args, **kwargs):
kwargs.update({'cache_size':0})
return Jinja2Template.prepare(self, *args, **kwargs)
template = functools.partial(original_template, template_adapter=CustomJinja2Template)
This causes the templates to always reload, but only if a python module has been touched. i.e. if you just edit a template file, the changes won't take affect until you edit one of the python files that imports it. It seems as if the templates are still being cached somewhere.
Flask comes packaged with Jinja2, and hence we just need to install Flask.
July 20, 2021. Jinja2 is a popular text templating engine for Python that is also used heavily with Ansible. Many network engineers are familiar with it and with leveraging Jinja2 templates for device configurations.
Flask uses the Jinja template library to render templates. In your application, you will use templates to render HTML which will display in the user's browser. In Flask, Jinja is configured to autoescape any data that is rendered in HTML templates.
I resolved this issue by ditching bottle's template solutions completely and using pure jinja2. It seems that Jijnja's FileSystemLoader
is the only one, which can watch for file changes.
I defined new template
function as follows (it looks for files in views/
, just like bottle used to):
from jinja2 import Environment, FileSystemLoader
if local_settings.DEBUG:
jinja2_env = Environment(loader=FileSystemLoader('views/'), cache_size=0)
else:
jinja2_env = Environment(loader=FileSystemLoader('views/'))
def template(name, ctx):
t = jinja2_env.get_template(name)
return t.render(**ctx)
Then I use it like this:
@route('/hello')
def hello():
return template('index.tpl', {'text': "hello"})
The difference from bottle's API is that you have to include .tpl
in file name and you have to pass context variables as dictionary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With