【问题标题】:Import a Python module into a Jinja template?将 Python 模块导入 Jinja 模板?
【发布时间】:2011-06-17 05:41:18
【问题描述】:

是否可以将 Python 模块导入 Jinja 模板以便我可以使用它的功能?

例如,我有一个 format.py 文件,其中包含格式化日期和时间的方法。在 Jinja 宏中,我可以执行以下操作 吗?

{% from 'dates/format.py' import timesince %}

{% macro time(mytime) %}
<a title="{{ mytime }}">{{ timesince(mytime) }}</a>
{% endmacro %}

因为 format.py 不是模板,所以上面的代码给了我这个错误:

UndefinedError: the template 'dates/format.py' (imported on line 2 in 'dates/macros.html') does not export the requested name 'timesince'

...但我想知道是否还有其他方法可以实现这一目标。

【问题讨论】:

    标签: python jinja2 python-import


    【解决方案1】:

    在模板中,不,你不能导入 python 代码。

    这样做的方法是将函数注册为jinja2custom filter,像这样:

    在你的 python 文件中:

    from dates.format import timesince
    
    environment = jinja2.Environment(whatever)
    environment.filters['timesince'] = timesince
    # render template here
    

    在您的模板中:

    {% macro time(mytime) %}
    <a title="{{ mytime }}">{{ mytime|timesince }}</a>
    {% endmacro %}
    

    【讨论】:

    【解决方案2】:

    只需将函数传递给模板,就像这样

    from dates.format import timesince
    your_template.render(timesince)
    

    在模板中,就像调用任何其他函数一样,

    {% macro time(mytime) %}
        <a title="{{ mytime }}">{{ timesince(mytime) }}</a>
    {% endmacro %}
    

    函数是 Python 中的一等公民,因此您可以像传递其他任何东西一样传递它们。如果你愿意,你甚至可以传入整个模块。

    【讨论】:

      【解决方案3】:

      您可以通过将模块 __dict__ 作为参数提供给 jinja 模板渲染方法来导出模块中可用的所有符号。下面将向模板提供 __builtin__、inspect 和 types 模块的功能和类型。

      import __builtin__
      import inspect
      import types
      
      env=RelEnvironment()
      template = env.get_template(templatefile)
      
      export_dict={}
      export_dict.update(__builtin__.__dict__)
      export_dict.update(types.__dict__)
      export_dict.update(inspect.__dict__)
      
      result=template.render(**export_dict)
      

      在模板内,使用导出模块的功能,类似如下:

      {%- for element in getmembers(object) -%}
      {# Use the getmembers function from inspect module on an object #}
      {% endfor %}
      

      【讨论】:

        【解决方案4】:

        模板不知道import,但你可以用importlib 教它:

        import importlib
        my_template.render( imp0rt = importlib.import_module )  # can't use 'import', because it's reserved
        

        (您也可以通过使用dict 传递参数来将其命名为"import"

        kwargs = { 'import' : importlib.import_module }
        my_template.render( **kwargs )
        

        然后在 jinja-template 中,你可以导入任何模块:

        {% set time = imp0rt( 'time' ) %}
        {{ time.time() }}
        

        【讨论】:

          【解决方案5】:

          您可以像这样将模块传递给render 函数:

          from src.constants import proto
          
          wls = {"workloads": [{"name": "test1", "p": "UDP"}, {"name": "test2", "p": "TCP_NONTLS"}]}
          
          env = Environment(
                  loader=PackageLoader("src", "templates")
              )
          template = env.get_template("lds.yaml.j2")
          print(template.render(wls,proto=proto))
          

          在 jinja 模板中你现在可以使用proto:

          {% if workload.p == proto.udp -%}
          

          【讨论】:

            【解决方案6】:

            如果您使用的是 Flask,则可以使用 Flask context processor 将导入添加到 Jinja 上下文。例如,以下是如何使模块 datetimeemail.utilsos.path 在所有模板中可用:

            app = Flask(__name__)
            
            import email.utils, datetime, os.path
            @app.context_processor
            def add_imports():
                # Note: we only define the top-level module names!
                return dict(email=email, datetime=datetime, os=os)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-03-14
              • 1970-01-01
              • 1970-01-01
              • 2015-10-06
              • 1970-01-01
              • 1970-01-01
              • 2016-12-15
              • 1970-01-01
              相关资源
              最近更新 更多