<i id='m2fqp'></i>

          <span id='m2fqp'></span><i id='m2fqp'><div id='m2fqp'><ins id='m2fqp'></ins></div></i>

            <dl id='m2fqp'></dl>

            <code id='m2fqp'><strong id='m2fqp'></strong></code>
            <ins id='m2fqp'></ins>
            <fieldset id='m2fqp'></fieldset>

          1. <tr id='m2fqp'><strong id='m2fqp'></strong><small id='m2fqp'></small><button id='m2fqp'></button><li id='m2fqp'><noscript id='m2fqp'><big id='m2fqp'></big><dt id='m2fqp'></dt></noscript></li></tr><ol id='m2fqp'><table id='m2fqp'><blockquote id='m2fqp'><tbody id='m2fqp'></tbody></blockquote></table></ol><u id='m2fqp'></u><kbd id='m2fqp'><kbd id='m2fqp'></kbd></kbd>
          2. <acronym id='m2fqp'><em id='m2fqp'></em><td id='m2fqp'><div id='m2fqp'></div></td></acronym><address id='m2fqp'><big id='m2fqp'><big id='m2fqp'></big><legend id='m2fqp'></legend></big></address>

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

            • 时间:
            • 浏览:35457

             

            作者 | 单雨

            责编 | 屠敏

            模板继承

            简介

            模板继承允许你建立一个基本的"骨架"模板, 它包含了网站中所有常见的元素,并定义了可以被子模板覆盖的 块(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