2012-02-23 6 views
4

App EngineでPython 2.5を使用して、Jinja2 ModuleLoaderを動作させようとしました。私が使用する環境の初期化にPythonモジュールのJinjaテンプレート(プリコンパイル済みテンプレート)

: 'コンパイル'

@staticmethod             # get Jinja environment (global) 
def get_new():             # and initialize Jinja environment 
    if myEnv._my_env == None : 
     path = os.path.join(os.path.dirname(__file__), 'compiled') 
     myEnv._my_env = Environment(loader = ModuleLoader(path))  

    return myEnv._my_env 

は私のGAEプロジェクトのディレクトリです。 しかし、私はいつもTemplateNotFound例外を受け取りますか?

私が使用してテンプレートをコンパイル:

env = Environment(extensions=['jinja2.ext.i18n']) 

    env.filters['euros'] = Euros 

    db_runtimes = Runtimes.all()              # the html templates saved in a db.Blob 
    for each in db_runtimes.fetch(999) : 
     key = each.key().name() 
     source = db.Blob(each.content).decode('utf-8') 
     name = key.split('.')[0] 
     raw = env.compile(source, name=name, filename=name + '.py', raw=True) 
     each.compiled = db.Blob(raw.encode('utf-8'))       # compile and save the .py 
     each.put() 

結果のコードは正常に見えます。何か案は? 私があなたを助けてくれることを願っています。 Rodrigo Moraesのこの記事は、Pythonモジュールからのテンプレートの読み込みが非常に高速であることを示しています。しかし、この2009年の概念証明では、コードを実行できるようにするためにJinjaコードを「ハッキング」しました。私はModuleLoaderが同じ仕事をするべきだと思います。 https://groups.google.com/group/pocoo-libs/browse_thread/thread/748b0d2024f88f64


testmod.pyは次のようになります。

from __future__ import division 
from jinja2.runtime import LoopContext, TemplateReference, Macro, Markup, TemplateRuntimeError, missing, concat, escape, markup_join, unicode_join, to_string, identity, TemplateNotFound 
name = u'testmod.py' 

def root(context, environment=environment): 
    if 0: yield None 
    yield u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0  Transitional//EN"\n"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml">\n<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n<title>TEST</title>\n</head>\n<body>\n\t<p>test template</p>\n</body>\n</html>' 

blocks = {} 
debug_info = '' 

とページハンドラ:

def get(self): 

    my_env = myEnv.get() 
    page = 'testmod.py' 
    template = my_env.get_template(page) 
    self.response.out.write(template.render({})) 

I'haveもの.py拡張子のないテンプレートを取得しようとしました。

+0

は、コンパイル/ app.yamlを中static_dirとして指定していますか? – geoffspear

+0

compiledはPythonパッケージですが、app.yamlにハンドラは必要ありません。 – voscausa

答えて

1

更新:

https://gist.github.com/voscausa/9154936

更新::私はCMSで使用するコードで、この要点を参照してください。今、私はPythonの27を使用していることができ、モジュールローダを作成することができたのですjinjaコンパイル済みのテンプレート(pythonコード)をパッケージまたはデータベース(package = None)からロードします。

はローダーを初期化するには、使用することができます。

from jinja2 import Environment 
Environment(auto_reload=False, loader = moduleloader.FileSystemModuleLoader(package)) 

class ModuleLoader(object): 
    """Base mixin class for loaders that use pre-parsed Jinja2 templates stored 
    as Python code. 
    """ 
    def get_module(self, environment, template): 
     raise TemplateNotFound(template) 

    def load(self, environment, filename, j_globals=None): 
     """Loads a pre-compiled template, stored as Python code in a template 
     module. 
     """ 
     if j_globals is None: j_globals = {'environment' : environment} 

     t = object.__new__(environment.template_class) 

     module = self.get_module(environment, filename) 
     name, blocks, root, debug_info = module.run(environment, t) # module run function  

     t.environment = environment 
     t.globals = j_globals 
     t.name = name 
     t.filename = filename 
     t.blocks = blocks 
     # render function and module 
     t.root_render_func = root 
     t._module = None 

     # debug and loader helpers 
     t._debug_info = debug_info 
     t._uptodate = lambda: True 
     return t 

class FileSystemModuleLoader(ModuleLoader): 

    def __init__(self, package = None): # load module from package or datastore 
     self.package = package   # package = "compiled" or package = None 

    def get_module(self, environment, template): 
     # Convert the path to a module name 
     name = template.replace('.html', '').replace('.txt','').replace('/', '.') # NO extensions 
     module = None 

     if self.package == None : 
      if name in sys.modules : return sys.modules[name] 
      logging.info('load module : ' + name)  # load module from runtimes db 
      try : 
       runtime = models.Runtimes.get_by_key_name(template) 
       module_code = db.Text(runtime.compiled)         
       module = imp.new_module(name) 
       exec module_code in module.__dict__           
       sys.modules[name] = module    # add to sys modules, so no import 
       return module 
      except (ImportError, AttributeError): 
       logging.error('load failed : ' + name) 

     else :           # load module from package 
      logging.info('load module : ' + name + ' from package : ' + self.package) 
      try: 
       mod_import = __import__(self.package, globals(), None, [str(name)]) 
       module = getattr(mod_import, name) 
       return module 
      except (ImportError, AttributeError): 
       logging.error('load failed : ' + name) 

     raise TemplateNotFound(template) 
0

デベロッパー環境でテンプレートをあらかじめコンパイルして展開しているとします。 展開された環境でファイルにアクセスできることを確認しましたか?

+0

私はすべてのHTMLテンプレートがblobプロパティに格納されているJinja CMSを書いています。 Jinja FunctionLoaderを使用して、CMSからHTMLテンプレートを読み込みます。これは正常に動作します。今、これらのHTMLテンプレートをPythonコードにコンパイルしてダウンロードし、プロジェクトのディレクトリに保存しました。 – voscausa

+0

ちなみに、私はSDKで同じ問題を抱えていますが、コードはうまく見えますが、これらの行はPyDev Eclipseのdef root(context、environment = environment)エラーを報告します – voscausa

+0

import like:from compiled import testmodはモジュールにアクセスできます。私はまた、app.yamlのパスの静的ディレクトリを追加しました – voscausa

0

私はModuleLoaderをあきらめ、Rodrigo Moraesのソリューションに戻りました。私はJinja2コードを "ハックする"必要はありませんでした。私は環境を得るために、生成されたソースに2行のコードを挿入することを選択します。

from templating import myEnv 
environment = myEnv.get()     # get (and initialize) the Jinja Environment global 

そして私はのModuleLoaderでロドリゴのロード機能変更:

def load(self, environment, filename, j_globals=None): 
    """Loads a pre-compiled template, stored as Python code in a template 
    module. 
    """ 
    if j_globals is None: j_globals = {'environment' : environment} 

    t = object.__new__(environment.template_class) 

    module = self.get_module(environment, filename) 
    # name, blocks, root, debug_info = module.run(environment, t) CHANGED THE HACK 

    t.environment = environment 
    t.globals = j_globals 
    t.name = module.name 
    t.filename = filename 
    t.blocks = module.blocks 

    # render function and module 
    t.root_render_func = module.root 
    t._module = None 

    # debug and loader helpers 
    t._debug_info = module.debug_info 
    t._uptodate = lambda: True 
    return t 

を、その結果は非常に有望に見えます。

+0

しかしパフォーマンスはあまり良くありませんでした。そこで、コンパイラがハックとラン関数で生成したコードを変更しました。今はかなり速いです。 Jinja ModuleLoaderの使い方の例を誰かが提供することを期待しています。 – voscausa

関連する問題