Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is the preferred method to use jinja2 on App Engine?

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/templates where jinja2 is imported directly:

import jinja2
import os

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))

class MainPage(webapp2.RequestHandler):
    def get(self):
        greetings = 'somestring'
        template_values = {
            'greetings': greetings,
        }
        template = jinja_environment.get_template('index.html')
        self.response.out.write(template.render(template_values))

But I'm currently bolting on Simpleauth (https://github.com/crhym3/simpleauth) which follows the implementation that Nick Johnson described here: http://blog.notdot.net/2011/11/Migrating-to-Python-2-7-part-2-Webapp-and-templates where jinja2 is imported from webapp2_extras:

import os
import webapp2
from webapp2_extras import jinja2

class BaseHandler(webapp2.RequestHandler):
  @webapp2.cached_property
  def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

  def render_template(self, filename, **template_args):
        self.response.write(self.jinja2.render_template(filename, **template_args))

class IndexHandler(BaseHandler):
  def get(self):
    self.render_template('index.html', name=self.request.get('name'))

Which of these is the preferred method for using jinja2? (They don't seem to play together nicely, and would prefer to standardize on the best option.)

like image 473
Jed Christiansen Avatar asked Oct 23 '12 00:10

Jed Christiansen


2 Answers

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
like image 106
Roland Puntaier Avatar answered Oct 24 '22 10:10

Roland Puntaier


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).

like image 25
alex Avatar answered Oct 24 '22 10:10

alex