I originally implemented Jinja2 on App Engine using the examples shown on the App Engine site here: https://developers.google.com/appengine/docs/python/gettingstartedpython27/te
TL;DR: Use option #2
If you don't use i18n, then it doesn't matter much. But in the real world people speak different languages than English, and there is a tricky issue with jinja2 i18n on GAE: Threading (i.e. threadsafe: true
in app.yaml) is on by default and important for performance, but most jinja2 i18n docs that you can find on the web are not thread safe. Since you don't want to explicitly pass down the locale to each jinja2 macro, it needs to be held in a thread-local variable. This is what webapp2_extras.jinja2
does correctly.
I had the same question, but the answers here do not satisfy me.
I think it's about encapsulation vs performance. For a small application you can have a global, no problem. So the first solution is just fine. It lets you solve an easy problem in an easy way, without the overhead to learn the details of a framework.
For a bigger application you probably like to encapsulate and bring some order into your objects. Basically you make a framework, an infrastructure for scalability. But that's what webapp2 is supposed to give you.
The basic problem behind it: If you decide to make a singleton type of object local to a class that gets instanciated and freed as part of the logic (like webapp2.RequestHandler classes in official examples), then that referenced object (jinja2) will be released when the last class instance is gone... you might get a lot of freeing and reallocating. So its good to have a link to an object somewhere (webapp2.registry) to prevent removing even if not referenced anywhere else. It's like global, but without poluting the global namespace, and it is accessible from everywhere through webapp2.get_app().registry. It's also caching. Then, with cached_property you do just another layer of caching.
In short: If you want to encapsulate you better add caching for your app to stay efficient
In this case you go for the webapp2_extra jinja2 and in every module you can access the same jinja environment with:
jinja2.get_jinja2().environment
The first method is a very basic example.
The second (with the BaseHandler) is the preferred method. Here you put the webapp2 shared methods. These methods can be used by derived classes and here you put webapp2 methods you want to override like dispatch.
I guess they are pretty much the same. What webapp2_extras.jinja2 does in addition is that it caches jinja2.Environment() initialization (for the request duration). Plus, you can leverage config/registry system of the webapp2.
Looking at get_jinja2() source you'll see that it's just a handy wrapper for jinja2.Environment() with some default environment args and enabled extensions (e.g. i18n).