业务微信 | 电话:18012713873

轻松搞定 Django 模板语言进阶!

·文章编辑:林风·所属栏目:SEO优化
关键词:

 

作者 | 单雨

责编 | 屠敏

模板继承

简介

模板继承允许你建立一个基本的"骨架"模板, 它包含了网站中所有常见的元素,并定义了可以被子模板覆盖的 块(blocks)  。示例:

假如父模板base.html如下:

<!DOCTYPE html>

<htmllang="en">

<head>

<linkrel="stylesheet"href="style.css">

<title>{% block title %}My amazing site{% endblock %} </title>

</head>

<body>

<divid="sidebar">

{% block sidebar %}

<ul>

<li><ahref="/">Home </a></li>

<li><ahref="/blog/">Blog </a></li>

</ul>

{% endblock %}

</div>

<divid="content">

{% block content %}{% endblock %}

</div>

</body>

</html>

它定义了一个简单的 HTML 骨架文档, 假设这是一个简单的两列页面  。子模板的工作就是填充空的 块(block) 中的内容 。

在这个例子中, block 标签定义了三个可以被子模板填充的块  。block标签告诉了模板系统哪些地方可能被子模板覆盖  。例如 ,子模板可能如下:

{% extends "base.html" %}

{% block title %}My amazing blog{% endblock %}

{% block content %}

{% for entry in blog_entries %}

<h2>{{ entry.title }} </h2>

<p>{{ entry.body }} </p>

{% endfor %}

{% endblock %}

extends 标签告诉模板系统这个模板继承了另外的模板  。当模板系统对此模板进行运算时, 首先会寻找他的父模板 ——在这里是"base.html"  。

在这一点上, 模板引擎会在 base.html 中发现三个 block 标签, 并且使用子模板的内容替换掉这些块  。根据变量blog_entries 的值, 输出可能看起来像这样:

<!DOCTYPE html>

<htmllang="en">

<head>

<linkrel="stylesheet"href="style.css">

<title>My amazing blog </title>

</head>

<body>

<divid="sidebar">

<ul>

<li><ahref="/">Home </a></li>

<li><ahref="/blog/">Blog </a></li>

</ul>

</div>

<divid="content">

<h2>Entry one </h2>

<p>This is my first entry. </p>

<h2>Entry two </h2>

<p>This is my second entry. </p>

</div>

</body>

</html>

注意:因为子模板没有定义 sidebar 块, 那么父模板的内容就会被使用  。通常来说, 父模板 {% block %} 中的内容会被作为备用的内容 ,在子模板没有覆盖时就会被使用  。

多重继承

模板继承可以是多重继承  ,多重继承常见的模式是:

  • 创建一个 base.html 模板把控网站的整体风格 。
  • 为网站的每个子分类创建一个 baseSECTIONNAME.html模板. 比如, basenews.html, base_sports.html 。 这些模板都继承 base.html 模板  。这些模板中包含特定的设计/风格  。
  • 为每一种类型的页面创建一个模板, 比如 news article 或blog 内容  。这些模板扩展上一级模板的相应分类  。

上述的关系可以用下图表示:

这样就能最大限度的重用模板代码 ,比如在所有页面通用的导航栏 。

模板继承注意事项

  • {% extends %}必须位于模板的最开始  , 如果在其他的部分声明, 则不生效  。
  • 在基础模板尽可能多的使用{%block%} ,子模板不需要定义所有父模板中的块, 所以你可以在若干的块中填充默认值, 然后定义之后需要自定义的块  , 有更多的可用块总是更好的  。
  • 如果发现自己在许多模板中有重复内容的了, 这可能需要移动这些内容到父模板的 {% block %} 中  。
  • 如果需要得到父模板块中的内容, 可以用{{ block.super }} 变量  。使用 {{ block.super }} 插入的数据不会被自动转义  ,因为它已经被转义了  。如果需要转义, 可以在父模板中转义 。
  • 使用模板标签在{% block %}块外部创建的变量不能在块内使用 。例如  ,这个模板不渲染任何东西:

{% trans "Title"astitle %}

{% block content %}{{ title }}{% endblock %}

  • 为了具有更好的可读性  ,也可以给{% endblock %}块标签定义一个名字  。例如:

{% block content %}

...

{% endblock content %}

在一个较长的模板中, 这个方法可以让你知道是哪一个{% block %} 标签定义结束了 。

  • 不能在同一模板中定义多个具有相同名称的块标签 。存在这个限制是因为{%block%}标签是"双向"定义的  。也就是说, 它不仅指定了子模板要填充父模板的哪个块, 也说明了父模板要引用哪些子模板块的内容  。所以在子模板中有多个同名的{%block%}标签时, 父模板就不知道到底要引用子模板中哪个块的内容了  。

自动HTML转义

从模板直接生成HTML存在XSS风险

从模板生成HTML时, 总是有一种风险, 即一个变量将会影响生成的HTML字符 。考虑这个模板片段:

Hello, {{ name }}

看起来可能没有什么风险  ,但是如果用户输入的名字为一个HTML代码:

<>alert('hello')</>

当{{name}}为这个值时  ,模板将呈现为:

Hello, <>alert('hello')</>

这将使浏览器弹出一个弹出一个Java警告 。同样的  ,考虑另外一种情况:

如果名字中包含一个 '<' 符号:

<b>username

对应的模板将为:

Hello, <b>username

这意味着在此之后的文字将呈现为粗体  。

由此带来一个风险:

用户提交的数据是不可靠的且不应被直接插入到您的网页, 因为恶意用户可以使用这种潜在的漏洞做危害网站的事情 。这种类型的安全漏洞被称为 Cross Site ing (跨站脚本) (XSS) 攻击  。

使用转义避免XSS风险

(1)使用escape标签

确保让不受信任的变量经过了 escape 过滤器 , 将危险的HTML字符替换为无害的HTML转义字符  。但是这常常被忽略  。

(2)使用自动转义

在Django中, 默认每个模板会自动转义输出的每一个变量标签  。具体来说, 这五个字符会被转义:

  • < 被替换为 <
  • > 被替换为 >
  • ' (单引号) 被替换为 '
  • " (双引号) 被替换为 "
  • & 被替换为 &

这种行为是默认的  。如果使用的是Django的模板系统, 自然拥有这种保护  。

关闭自动转义

可以在站点 ,模板和变量三个层级关闭自动转义  。

(1)对单个变量

要为一个单独的变量禁用自动转义, 使用 safe 过滤器(https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#std:templatefilter-safe):

This will be escaped: {{ data}}

This will not be escaped: {{ data|safe }}

如果变量中包含“”字符  ,输出也是“”  。

(2)对于模板文本块

要在模板中控制自动转义, 可以在整个模板 (或者模板的特定区域) 使用 autoescape 标签, 如:

{% autoescape 

相关阅读

自媒体代运营是什么意思

2020-05-29
自媒体代运营是什么意思...查看全文

自媒体运营公司有哪些

2020-05-29
自媒体运营公司有哪些...查看全文

自媒体第三方代运营公司排名

2020-05-29
自媒体第三方代运营公司排名,自媒体第三方代运营公司...查看全文
网站地图
扫描二维码分享到微信
确 认

网站地图 | 导航地图|无限传媒

咨询反馈
扫码关注

微信公众号