【问题标题】:Which is the preferred method to use jinja2 on App Engine?在 App Engine 上使用 jinja2 的首选方法是哪种?
【发布时间】:2012-10-23 00:35:51
【问题描述】:

我最初使用 App Engine 网站上显示的示例在 App Engine 上实现了 Jinja2:https://developers.google.com/appengine/docs/python/gettingstartedpython27/templates 其中 jinja2 是直接导入的:

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

但我目前正在使用 Simpleauth (https://github.com/crhym3/simpleauth),它遵循 Nick Johnson 在此处描述的实现:http://blog.notdot.net/2011/11/Migrating-to-Python-2-7-part-2-Webapp-and-templates 其中 jinja2 是从 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'))

以下哪种方法是使用 jinja2 的首选方法?(它们似乎不能很好地结合在一起,并且更愿意标准化最佳选择。)

【问题讨论】:

    标签: python google-app-engine jinja2


    【解决方案1】:

    我也有同样的问题,但这里的答案并不让我满意。

    我认为这是关于封装与性能的关系。对于小型应用程序,您可以拥有全局,没问题。所以第一个解决方案很好。它可以让您以一种简单的方式解决一个简单的问题,而无需学习框架的细节。

    对于更大的应用程序,您可能喜欢封装对象并为其添加一些顺序。基本上,您创建了一个框架,一个可扩展性的基础设施。但这就是 webapp2 应该给你的。

    其背后的基本问题: 如果您决定将单例类型的对象作为逻辑的一部分实例化和释放的类本地化(如官方示例中的 webapp2.RequestHandler 类),那么该引用的对象(jinja2)将在最后一个类实例时释放不见了……你可能会得到很多释放和重新分配。因此,最好在某个地方(webapp2.registry)有一个对象的链接,以防止即使没有在其他任何地方引用也能被删除。它就像全局,但不会污染全局命名空间,并且可以通过 webapp2.get_app().registry 从任何地方访问它。它也是缓存。然后,使用 cached_property 你只做另一层缓存。

    简而言之:如果您想封装,最好为您的应用添加缓存以保持高效

    在这种情况下,您可以使用 webapp2_extra jinja2,并且在每个模块中,您都可以使用以下方式访问相同的 jinja 环境:

    jinja2.get_jinja2().environment
    

    【讨论】:

      【解决方案2】:

      我猜它们几乎是一样的。 webapp2_extras.jinja2 还做的是缓存 jinja2.Environment() 初始化(对于请求持续时间)。另外,您可以利用 webapp2 的配置/注册表系统。

      查看get_jinja2() source,您会发现它只是一个方便的 jinja2.Environment() 包装器,带有一些默认环境参数和启用的扩展(例如 i18n)。

      【讨论】:

        【解决方案3】:

        第一种方法是一个非常基本的例子。

        第二种(使用 BaseHandler)是首选方法。在这里,您放置了 webapp2 共享方法。这些方法可以被派生类使用,在这里你可以放置你想要重写的 webapp2 方法,比如 dispatch。

        【讨论】:

          【解决方案4】:

          TL;DR:使用选项 #2

          如果你不使用 i18n,那也没关系。但在现实世界中,人们说的语言与英语不同,并且 GAE 上的 jinja2 i18n 存在一个棘手的问题:线程(即 app.yaml 中的 threadsafe: true)默认开启并且对性能很重要,但大多数 jinja2 i18n 文档认为你可以在网上找到不是线程安全的。由于您不想将语言环境显式传递给每个 jinja2 宏,因此需要将其保存在线程局部变量中。这就是webapp2_extras.jinja2 正确的做法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-17
            • 2012-08-23
            • 2012-08-17
            • 1970-01-01
            • 2011-01-22
            • 2012-06-06
            相关资源
            最近更新 更多