Django:使用Extends还是Include?

14

我和我的朋友有一个小争论。在我的 Django 项目中,我创建了一个名为 menu.html 的文件,其中包含一堆已经配置和格式化成列表的链接。现在我正在使用以下 Django/Python 代码将菜单包含到每个页面中,而不是手动硬编码到每个页面中:

{% include 'menu.html' %}

然而,我的朋友建议这并不是正确的做法。他说我需要使用extends而不是include,然后定义内容,就像这样:

{% extend 'menu.html' %}
{% block content %}
The rest of my content here.
{% endblock %}

这是一些额外的代码。我使用哪个真的很重要吗?我更喜欢使用前者。

3个回答

14

是的,这很重要。首先,extends 只能出现在文件的第一行。其次,include 会在解析堆栈上推送和弹出一个上下文对象,这意味着在 include 中创建的值将会在返回时失效。

我的建议是:创建一个 base.html 模板文件,定义站点的整体结构,并在关键区域大量使用 {% block foo %} 标签。然后,所有其他模板都 extends 这个基础模板(或者继承该基础模板的其他模板),并根据需要替换这些块。

include 则适合封装可能需要在多个地方甚至同一页中使用的东西。

更新:

我自己的 template_tags 库已经使用了很长时间,以至于我忘记了 Django 的模板语言仍然存在重要功能缺陷。这里提到的标签来自早期的 Django 片段,名为 expr,我对它进行了大量的编辑和扩展。例如,您可以这样说:{% expr 'Fred' as name %}(或任何有效的 Python 表达式),它将在“当前上下文”中将结果存储在 'name' 位置。如果这发生在 included 模板中,则会在退出模板文件时弹出 name 的值。

您可以通过 {% with %} 标签来实现类似的功能,但是 expr 给了我更大的灵活性,包括执行任意复杂的调用。这最初是在创建复杂的缓存对象时出现的,这些对象需要进行昂贵的 DBMS 交互,而不能在视图中完成,必须在模板本身中调用。

如果需要深入了解,请给我发电子邮件(我的简介中有联系方式)。


2
你能用一个例子来解释一下吗:在include中创建的值将在返回时超出范围 - user
更新:哦,你在Django中几乎有Python!就像在Cheetah或Web2py中一样!太棒了! - mirek

3

(他的朋友)

我实际上想说的是定义一个base.html,这样你就可以继承一个包含多个通用部分的基础模板,其中包括doctype、html元素定义的3个内容块和导航以及可选区域来覆盖/插入头部的脚本/link元素。

<!doctype>
<html>
<head>
{%block extrahead %} {%endblock %}
</head>
{%block nav %}
<nav>
  <ul>
    <li>home</li>
  </ul>
</nav>
<div id="content">
{% endblock %}
{%block content %}
{% endblock %}
</div>
</html>

然后您可以定义homepage.html:
{% extends "base.html" %}

{% block content %}
homepage content
{% endblock %}

homepage.html会有导航,因为它继承了base.html


3
在这种情况下,将菜单放置在base.html中并从此处扩展似乎更有意义。
使用include可以很好地拆分复杂的模板并重用这些块。
比方说,你在网站的不同地方使用了相同的列表样式,但是你发送给它的查询集是不同的。只要你调用相同的查询集,你只需要写一次模板代码。 这里我为普通请求和ajax请求使用了不同的模板。但是使用include让我在两个模板中重用大部分内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接