【问题标题】:Django: nested content blocks with the same nameDjango:同名的嵌套内容块
【发布时间】:2011-09-19 14:18:24
【问题描述】:

有没有办法让内容块具有相同的名称?

base.html:

这是带有主要布局的模板。

<html>

  ...

  {% block content %}

  {% endblock %}

  ...

</html>

base_side_left.html:

这是左侧有主布局+侧边栏的模板。

{% extends 'base.html' %}

{% block content %}

  <div class='sidebar'>
  </div>

  {% block content %}

    //This doesn't work because you can't have blocks with the same name//

  {% endblock %}

{% endblock

我问这个问题有几个原因:

  1. 无需更改内容块的名称即可轻松更改页面的父级。
  2. 我不必为我的积木起名字。比如内容内容、侧边栏内容等

我有两个我不喜欢的解决方案,因为它们不干燥:

  1. 将侧边栏设为部分并将其包含在您需要的模板中。
  2. 将所有内容添加到基本模板并覆盖您不需要的那些块。

如果 Django 模板无法做到这一点,我可以用其他模板引擎做类似的事情吗?

小更新:

所以我想要做的是能够在模板树中移动模板而不会有太多麻烦。虽然没有为我的内容块提供智能名称,但这是不可能的,但我想我还是添加了这个漂亮的图表。

【问题讨论】:

  • 您能解释一下为什么您认为这是个坏主意吗?
  • Mike 在下面阐述了我的大部分原因

标签: django templates


【解决方案1】:

不,你不能。来自Django docs on template inheritance

您不能在同一个模板中定义多个具有相同名称的{% block %} 标签。存在此限制是因为块标签在“两个”方向上工作。也就是说,块标签不仅提供了一个要填充的洞——它还定义了填充 parent 中的洞的内容。如果模板中有两个名称相似的{% block %} 标签,则该模板的父级将不知道要使用哪个块的内容。

我不清楚你为什么要这样做。

无需更改内容块的名称即可轻松更改页面的父级。

只有一个{% block %} 具有给定名称的标签,并且也只有一个{% extends %} 标签。我看不出难度有什么不同。

我不必为我的积木起名字。比如内容内容、侧边栏内容等

任何维护您的代码的人都会很快忘记哪个content 块是有效的并且会感到困惑。此外,名称应该与{% block %} 应该做的事情有关。所以我想知道为什么你会有两个模板,一个包含另一个,块完全相同。

另一点来自docs

如果您发现自己在多个模板中重复内容,这可能意味着您应该将该内容移动到父模板中的 {% block %}。

这使您可以将重复的标记设为默认值,并且您可以在需要的地方覆盖它。

这也可能有帮助:

如果您需要从父模板中获取块的内容,{{ block.super }} 变量就可以解决问题。如果您想添加到父块的内容而不是完全覆盖它,这很有用。使用{{ block.super }} 插入的数据不会被自动转义(参见下一节),因为如果需要,它已经在父模板中转义了。

据我所知,这可能是您的最佳选择:

将侧边栏设为部分并将其包含在您需要的模板中。

这怎么不干?你必须重复{% include %}标签吗?

我认为有一个更好的设计解决方案对你有用,但你没有提供足够的信息来说明你想要完成的工作,以便我进一步提供帮助。

编辑:看看你的例子,你可以用一个模板来做所有的事情。CSS会在这里照顾你。

page_template.html:

<!DOCTYPE html PUBLIC -- ... -->
<html>
<head>
    <!-- ... other header fields ... -->
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <base href="{{ host }}{{ root }}{{ path }}" />
    <title>{% block title %}Untitled{% endblock %}</title>
    <link rel="icon" type="image/png"
        href="{{ root }}static/images/favicon.png" />
    <link rel="stylesheet" type="text/css"
        href="{{ root }}static/css/general.css" />
    <!-- other header fields here -->
{% block head %}{% endblock %}
</head>
<body class="{% block page_class %}no_sidebar{% endblock %}">
    <div id="page_header">
        <!-- page heading here -->
    </div>
    <div id="sidebar">
        {% block sidebar %}<!-- default sidebar here -->{% endblock %}
    </div>
    <div id="banner">
        {% block banner %}{% endblock %}
    </div>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

general.css:

body.no_sidebar div#sidebar,
div#banner
{
    display: none;
}

div#sidebar
{
    width: 20%;
}

body.with_sidebar div#sidebar
{
    float: left;
}

body.with_banner div#banner
{
    display: block;
}

body.right_sidebar div#sidebar
{
    float: right;
}

那么你的页面看起来就像,按照你的例子的顺序:

plain_old_page.html:

{% extends base.html %}

{% block content %}
    <!-- content goes here -->
{% endblock %}

page_with_left_sidebar.html:

{% extends base.html %}
{% block page_class %}with_sidebar{% endblock %}

{% block sidebar %}
    <!-- sidebar goes here, if different from default -->
    <!-- otherwise omit this section -->
{% endblock %}

{% block content %}
    <!-- content goes here -->
{% endblock %}

page_with_left_sidebar_and_banner.html:

{% extends base.html %}
{% block page_class %}with_sidebar with_banner{% endblock %}

{% block sidebar %}
    <!-- sidebar goes here, if different from default -->
    <!-- otherwise omit this section -->
{% endblock %}

{% block banner %}
    <!-- banner goes here -->
{% endblock %}

{% block content %}
    <!-- content goes here -->
{% endblock %}

page_with_right_sidebar.html:

{% extends base.html %}
{% block page_class %}right_sidebar{% endblock %}

{% block sidebar %}
    <!-- sidebar goes here, if different from default -->
    <!-- otherwise omit this section -->
{% endblock %}

{% block content %}
    <!-- content goes here -->
{% endblock %}

【讨论】:

  • 好像我在问一些奇怪的事情。我对 IRC 也有类似的反应。我在其他语言中使用了这种技术,其中模板确实支持具有相同名称的嵌套块,我认为它工作得非常好。我不认为其他人维护它是一个大问题。他们只需要一直遵循扩展直到基本模板。包含标签不是这样干的,因为我必须重复它。对于侧边栏,它是可行的,但如果您有其他共享部分怎么办。无论如何,我这里的空间有限,所以我会利用剩余的空间来感谢您抽出时间来回答:谢谢:)
  • 您可以随时编辑问题以提供更多详细信息。那里没有空间限制。我仍然认为有更好的方法来做你想做的事,如果我知道你想做什么。
  • 稍微更新了问题,但我认为您的回答已经告诉我不可能按照我想要的方式。
猜你喜欢
  • 1970-01-01
  • 2019-06-07
  • 2010-12-26
  • 2016-12-19
  • 2011-07-28
  • 1970-01-01
  • 2020-05-17
  • 2021-12-01
  • 2015-04-28
相关资源
最近更新 更多