【问题标题】:Multiple level template inheritance in Jinja2?Jinja2中的多级模板继承?
【发布时间】:2010-12-30 21:42:08
【问题描述】:

我从事 html/css 的交易,我一直在从事和关闭 django 项目作为模板设计师。我目前正在一个使用 Jinja2 的网站上工作,我已经使用了大约 2 周。我刚刚通过阅读文档发现 Jinja2 不支持多级模板继承,因为你不能做多个

{% extends "foo" %}

每次渲染。现在我很确定你可以在 Django 中做到这一点,它很强大,因为你可以指定一个基本模板,基于它指定 3 或 4 个模板,然后使用这些基本模板构建你的页面。继承的重点不是让你有更多的抽象能力,所以你唯一真正搞砸的不是唯一的代码吗?

无论如何,我不知道在这里做什么。我不知道是否有某种方法可以像使用 Django 模板一样工作。我不是 Django 或 Jinja(2) 方面的专家,但我可以提供所需的任何信息。

【问题讨论】:

  • 请提供说明 Jinja2 不能进行多级继承的链接。您是否尝试过使用模板层次结构?你遇到了什么错误?
  • jinja.pocoo.org/2/documentation/templates#extends - “不支持多重继承。”
  • @xckpd7:多重继承与多级单继承不同。我也看不到 Django 中对多重继承的支持。请提供一些示例来说明您是在谈论多级继承还是实际的多级继承。
  • @S.Lott:我想做的就是拥有一个基本模板,基于该模板拥有 3 或 4 个基本模板,并能够基于这些模板创建模板,以提供极致的灵活性。我的印象是您通过在子基础模板和单个 html 模板上指定扩展来做到这一点,这可能是 2 个或更多 {% extends %} 标签,因此违反了说明您的文档部分每次渲染只能使用一个 {% extends %}。我可能是对的,也可能是错的,但鉴于我所问的,有没有办法做到这一点?
  • @xckpd7:请不要在您自己的问题上编写扩展的 cmets。请更新问题。请提供一个你认为你想做的例子。请提供您实际遇到的问题。您可以拥有任何深度的模板层次结构,因此我不明白您当前尝试使用的解决方案有什么不工作的地方。请使用示例代码更新问题。

标签: python css django django-templates jinja2


【解决方案1】:

多重继承和多级继承是不一样的。我知道这个问题与后者有关。

让我展示一下我的解决方法:

父模板.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset='utf-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Your Title</title>
    <link rel='stylesheet' href="{{ url_for('static', filename='css/main.css') }}">
    {% block head %}{% endblock %}
</head>

<body>
    {% block nav %}{% endblock %}
    {% block body %}{% endblock %}
</body>

</html>

子模板.html

{% extends 'parent-template.html' %}

{% block nav %}
<header>
    <div>
        <nav>
            ...
            [navbar html code]
            ...
        </nav>
    </div>
</header>
{% endblock %}

login.html(我不需要导航栏)

{% extends 'parent-template.html' %}

{% block body %}
<header>
    ...
    [header html code]
    ...
</header>
<main>
    ...
    [main html code]
    ...
</main>
{% endblock %}

home.html(我需要导航栏的地方)

{% extends 'child-template.html' %}

{% block body %}
<main>
    ...
    [main html code]
    ...
</main>
{% endblock %}

login.html 和 home.html 都使用父模板中的所有数据,但只有 home.html 使用子模板(导航栏)中的数据。

【讨论】:

    【解决方案2】:

    苦苦挣扎了好久,找到{{super}} 用于jinja2模板中的多级继承。

    以下内容灵感来自https://stackoverflow.com/a/31093830/1300775

    base.html

    <html>
    <body>
      {% block title %}
        Brand
      {% endblock %}
    </body>
    

    layer-1.html

      {% extends "base.html" %}
      {% block title %}
        {{ super() }} - Section
      {% endblock %}
    

    layer-2.html

      {% extends "layer-1.html" %}
      {% block title %}
        {{ super() }} - Article
      {% endblock %}
    

    渲染模板layer-2.html 将输出Brand - Section - Article(由于缩进,给或取几个空格字符)。

    【讨论】:

    • 不知道为什么有人给你-1,但这是我想要将我的应用程序嵌入现有仪表板布局中的原因
    • @mLstudent33,如果答案是您想要的,请继续投票(点击分数上方的三角形)。
    • 完美运行!满足了我的要求,节省了很多时间。
    【解决方案3】:

    您可以使用以下方式将不同的内容组合成一个 layout.html 用于各种布局设计:

    {% if instance == 'type1' %}
    
    {% elif instance == 'type2' %}
    
    {% else %}
    
    {% endif %}
    

    ...然后调用:

    render_template('layout', instance='%s' % instance)
    

    在python代码中。

    【讨论】:

      【解决方案4】:

      试试这个,感谢@Ixm 的回答,这对我有用。

      base.html

      <html xmlns="http://www.w3.org/1999/xhtml">
          <body>
            {% block content %}{% endblock %}
          </body>
      </html>
      

      content.html

      {% extends "base.html" %}
      {% block content %}
      <table>
        <tr>
        {% include "footer.html" %}
        </tr>
      </table>
      {% endblock %}
      

      footer.html

      {% block footer %} <td> test</td>{% endblock %}
      

      并调用

      env = Environment(loader=FileSystemLoader(os.path.join(path, "Layouts")))
      template = env.get_template('content.html')
      html = template.render()
      print html
      

      【讨论】:

      • 这个问题仍然有很多生命,即使是5年后!很有趣。
      • 如果包含页脚,为什么还需要块?
      • @Rey - 让我们在 11 年后实现它!不错。
      【解决方案5】:

      我最近遇到了同样的问题。我想继承几个子模板并且它起作用了。为了说明这一点,我想向您展示一个对我有用的解决方案:

      我有一个 base.html 文件,它包含块内容并由 manage.html 扩展。并且 manage.html 有一个由 internet_market.html 扩展的块 sub_manage,所以在视觉上它看起来像:

      |- base.html (block content)
      |--manage.html (extends base.html)
      |---sub_manage.html (extends manage.html)
      

      当我渲染它时,everythink 工作正常,这意味着您可以在一次渲染中拥有多个 {% extends %}。唯一的问题是,如果您使用 css 或 js 文件的相对链接,那么它可能不起作用,而是会呈现,但它不会找到您的 css/js 文件。 喜欢:

      <head>  
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <link rel="stylesheet" type="text/css" href="../static/css/bootstrap.min.css">
      <script type="text/javascript" src="../static/js/bootstrap.min.js"></script>
      <style type="text/css">
      </head>
      

      在这种情况下,您必须使用 url_for 来使用动态链接。喜欢:

      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <link rel="stylesheet" type="text/css" href="{{url_for("static", filename = "css/bootstrap.min.css")}}">
      <script type="text/javascript" src="{{url_for("static", filename = "js/bootstrap.min.js")}}"></script>
      <style type="text/css">
      

      【讨论】:

        【解决方案6】:

        请参阅文档 extendingincludingimporting

        这提供了从多个文件中获取功能以用于不同目的的方法,并且与嵌套的深度不同。 您可以完美地拥有一个扩展模板的模板...

        【讨论】:

          【解决方案7】:

          使用 jinja2 实现多级模板的最佳方法之一是使用“包含” 假设你有 'base_layout.html' 作为你的基本模板

          <!DOCTYPE html>
          <title>Base Layout</title>
          <div>
            <h1>Base</h1>
            .... // write your code here
            {% block body %}{% endblock %}
          </div>
          

          然后您希望拥有扩展“base_layout”的“child_layout.html”。

          {% include "base_layout.html" %}
            <div>
            ... // write your code here
            </div>
          {% block body %}{% endblock %}
          

          现在您的页面可以扩展 'child_layout.html' 并且它将同时具有 base_layout.htmlchild_layout.html

          {% extends "child_layout.html" %}
          {% block body %}
            ...// write your code here
          {% endblock %}
          

          【讨论】:

          • 如果我没记错的话,include 的问题是即使不需要该文件或者即使用户没有提出请求,它也会加载 html 文件。但是extends的优点是html文件是根据请求渲染的。这将节省加载整个页面的时间,尤其是当有大量包含大量代码的 html 文件时
          【解决方案8】:

          按照文档的措辞,它似乎不支持深度继承 (n) 级别。

          不像 Python Jinja 不支持 多重继承。所以你只能 有一个名为 per 的扩展标签 渲染。

          我不知道这只是一个规则说每个模板扩展 1....我现在知道了,在 jinja irc 频道的帮助下。

          【讨论】:

          • 我很高兴看到你解决了这个问题,我也在想同样的事情。我认为你原来的问题很清楚。在 StackOverflow 上处理自负可能会很烦人——在你问这个问题的那天,上面的某个人一定很暴躁。
          • 对于它的价值,我刚刚成功部署了 jinja2 的多级扩展,感谢这篇文章,所以我有一个 base.html,然后用进一步的 base_admin.html、base_client.html 扩展它, base_form.html 等,然后最后用实际页面扩展它们,比如accounts.html。不再重复代码!
          猜你喜欢
          • 1970-01-01
          • 2016-01-19
          • 2015-04-14
          • 2017-05-15
          • 2014-04-07
          • 2012-11-29
          • 2011-03-22
          • 2013-01-09
          • 2011-09-12
          相关资源
          最近更新 更多