3

Jinja2 コンパイル済みテンプレートとモジュール ローダーを使用して、コンパイル済みテンプレート (Python コード) をデータストアから読み込みます。しかし、テンプレートにマクロが含まれている場合、アプリ エンジンでは機能しません: TypeError: 'NoneType' object is not callable

しかし、アプリ エンジン SDK では問題なく動作します。マクロ呼び出しをスキップすると、同じエラーが発生します。

マクロがなくても問題なく動作します。このマクロの問題に対する解決策がないため、テンプレートで Python 関数を呼び出して、マクロの機能を実装します。

更新: これは、エラーが発生するテンプレート ソース コードです。

{% extends "mainpage.html" %}
{% block form %}
    {% macro test_macro(name) %}
        <p>{{ name }}</p>
    {% endmacro %}
    <div>
    {{ test_macro('John Doe') }}
    </div>
{% endblock %}

そして、これはコンパイルされたテンプレート コード (フォーム ブロック部分) です。

def block_form(context, environment=environment):
    if 0: yield None
    yield u'\n'
    def macro(l_name):
        t_1 = []
        pass
        t_1.extend((
            u'\n<p>', 
            to_string(l_name), 
            u'</p>\n', 
        ))
        return concat(t_1)
    l_test_macro = Macro(environment, macro, 'test_macro', ('name',), (), False, False, False)
    yield u'\n<div>\n\t%s\n</div>\n' % (
        context.call(l_test_macro, 'John Doe'), 
    )

更新:いくつかのデバッグの後、機能しました。でもわかる!!!問題: インポートを失います。そして、コードでインポートを再定義するとき。出来た。

モジュールの上部:

from __future__ import division
from jinja2.runtime import LoopContext, TemplateReference, Macro, Markup, TemplateRuntimeError, missing, concat, escape, markup_join, unicode_join, to_string, identity, TemplateNotFound
__jinja_template__ = None

それを機能させるには、インライン インポートを追加する必要がありました。

from jinja2.runtime import Macro     # import again ?????     
l_test_macro = Macro(environment, macro, 'test_macro', ('name',), (), False, False, False)    

誰かが説明できますか、どうすればインポートを失うことができますか??? この問題はアプリ エンジンでのみ発生し、SDK では発生しませんか ??? これは名前空間の問題ですか?

4

1 に答える 1

2

モジュールをsys.modulesに追加することで、それを解決することができました。しかし、マクロを使用したときに、GAEではなくSDKで機能した理由がわかりません

これが私の変更したモジュールローダーのコードです。

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 :                                           # load from db and not from package
        logging.info('load module : ' + name)                           # load module from runtimes db 
        if name in sys.modules : return sys.modules[name]               # already imported              
        try :
            runtime = models.Runtimes.rtimes_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 again
            return module
        except (ImportError, AttributeError):
            logging.error('load failed : ' + name)

    else : .... # load from package

    raise TemplateNotFound(template)
于 2012-11-21T15:17:02.017 に答える