在Django模板中复制数据的最佳方法是什么?

17 投票
4 回答
8285 浏览
提问于 2025-04-15 13:08
<html>
    <head>
        <title>{% block title %}{% endblock %}</title>
    </head>

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

这是我的模板,大致上就是这样。h1标题总是和标题标签一样。上面的这段代码是不合法的,因为不能有两个同名的块。我该怎么处理这个问题,才能避免重复呢?


补充说明一下:我有很多从这个模板继承的子模板,所以为每个模板创建一个新的{{title}}变量并不是一个很好的解决办法。之前我设置成这样:

base.html:

<title>{% block title %}{% endblock %}</title>

然后在base_view.html(扩展自base.html):

<h1>{% block title %}{% endblock %}</h1>

接着在base_object.html(扩展自base_view.html):

{% block title %}my title goes here{% endblock %}

这样就能正常工作。我重新整理了我的模板,现在只有base.html和base_object.html。我该怎么才能恢复之前的功能呢?

4 个回答

13
{% extends "base.html" %}

{% with "Entry Title" as title %}
    {% block title %}{{ title }}{% endblock %}
    {% block h1 %}{{ title }}{% endblock %}
{% endwith %}

如果你真的很担心在视图中出现 title 这个内容,并且想要避免重复的话,这样做是可行的。

25

在base.html文件中:

<head>
  <title>{% block title %}{% endblock %}</title>
</head>

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

接下来,创建一个新的“基础”层,叫做content_base.html(或者其他名字):

{% extends "base.html" %}

{% block h1 %}{% block title %}{% endblock %}{% endblock %}

现在,让你所有其他的模板都基于content_base.html。你在所有模板中的“title”块里写的内容,会同时出现在base.html中的“title”和“h1”块里。

8

看起来你的布局设计得不错。你有一个 base.html 模板,它定义了你应用中每个页面的基本结构和外观。还有一个 base_object.html 模板,它是基于这个基础模板扩展出来的。

你希望每个页面都有一个独特的标题和对应的 h1 标签(我想是这样)。实现这个的最好方法是在你的 base.html 模板中定义两个不同的区域。

<html>
    <head>
        <title>{% block title %}Default Title{% endblock %}</title>
    </head>

    <body>
        <h1>{% block h1 %}{% endblock %}</h1>
    </body>
</html>

在你的子模板中,如果你希望这两个区域的内容相同,就需要覆盖这两个区域。我知道你觉得这样有点反直觉,但这是因为 Django 处理模板继承的方式所决定的。

来源:Django 模板语言

最后要注意的是,在同一个模板中不能定义多个同名的 {% block %} 标签。这是因为一个块标签是双向的。也就是说,块标签不仅仅是提供一个可以填充的空洞,它还定义了填充这个空洞的内容。如果在一个模板中有两个同名的 {% block %} 标签,那个模板的父模板就不知道该用哪个块的内容了。

子模板看起来是这样的:

{% extends "base.html" %}
{% block title %}Title{% endblock %}
{% block h1 %}Title{% endblock %}

如果这让你觉得困扰,你可以在视图中为每个对象设置标题,作为一个模板变量。

{% block title %}{{ title }}{% endblock %}
{% block h1 %}{{ title }}{% endblock %}

Django 尽量把逻辑放在模板层之外。通常,标题是从数据库动态获取的,所以在视图层获取和设置这些信息是最合适的。如果你想使用默认标题(可能是在 base.html 中设置的),你也可以把标题留空,或者从 django.contrib.sites 包中获取网站名称。

另外,{{ block.super }} 可能会很有用。这个可以让你把父块的内容和子块的额外内容结合起来。所以你可以在基础模板中定义一个标题,比如 "Stackoverflow.com",然后在子模板中设置

{% block title %}{{ block.super }} - Ask a Question{% endblock %}

这样就能得到一个像 "Stackoverflow.com - Ask a Question" 的标题。

撰写回答