<dl id='y7wrx'></dl>
    <acronym id='y7wrx'><em id='y7wrx'></em><td id='y7wrx'><div id='y7wrx'></div></td></acronym><address id='y7wrx'><big id='y7wrx'><big id='y7wrx'></big><legend id='y7wrx'></legend></big></address>

    <ins id='y7wrx'></ins>

    <i id='y7wrx'></i>

    1. <fieldset id='y7wrx'></fieldset>

      <span id='y7wrx'></span>

      <i id='y7wrx'><div id='y7wrx'><ins id='y7wrx'></ins></div></i>
      1. <tr id='y7wrx'><strong id='y7wrx'></strong><small id='y7wrx'></small><button id='y7wrx'></button><li id='y7wrx'><noscript id='y7wrx'><big id='y7wrx'></big><dt id='y7wrx'></dt></noscript></li></tr><ol id='y7wrx'><table id='y7wrx'><blockquote id='y7wrx'><tbody id='y7wrx'></tbody></blockquote></table></ol><u id='y7wrx'></u><kbd id='y7wrx'><kbd id='y7wrx'></kbd></kbd>

        <code id='y7wrx'><strong id='y7wrx'></strong></code>

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

          • 时间:
          • 浏览:56009

           

          作者 | 单雨

          责编 | 屠敏

          模板继承

          简介

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