django 模板语言
Django的模板语言的目的是取得力量和易用性之间的平衡,与其他的模板语言相比,django模板语言显得更简单,更专一,
django模板系统由模板,变量,过滤器,标签,注释等主要部分组成
模板
一个模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道。
使用真实值替换变量,再返回最终得到的响应字符串,这一过程称之为渲染。模板可以生成任何基于文本的格式,html,csv,xml等等。
模板里面包含变量,过滤器,标签和注释,下面是一个简单的模板文件
{% extends "base_generic.html" %} {% block title %}{{ section.title }}{% endblock %} {% block content %} <h1>{{ section.title }}</h1> {% for story in story_list %} <h2> <a href="{{ story.get_absolute_url }}"> {{ story.headline|upper }} </a> </h2> <p>{{ story.tease|truncatewords:"100" }}</p> {% endfor %} {% endblock %}
变量
变量格式:{{ variable }}
变量解析:当模板引擎碰到一个变量的时候,会计算变量然后用结果去代替他
变量的命名:字母数字和下划线的组合,.(点号)不可用,因为点号有特殊的意义
如果变量不存在的时候,{{variable}}会被解析为''(一个空字符串)
点号(.)用来访问变量的属性。从技术上来说,当模版系统遇到点(“.”),它将以这样的顺序查询:
- 字典查询(Dictionary lookup)
- 属性或方法查询(Attribute or method lookup)
- 数字索引查询(Numeric index lookup)
过滤器
修改变量的展示方式
格式:{{ variable|filter }},展示变量经过filter后的结果,例如{{ name|lower }}战术name的小写形式,|是管道
filter可以串联,例如{{ text|escape|linebreaks }}
filter可以有参数,用冒号表示,例如 {{ bio|truncatewords:30 }}
filter参数如果有空格,必须用引号括起来,例如:{{ list|join:", " }}
常用的模版过滤器:
- default,如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:
{{ value|default:"nothing" }}
- length,返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
- filesizeformat,将该数值格式化为一个 “人类可读的” 文件容量大小 (例如 ‘13 KB’, ‘4.1 MB’, ‘102 bytes’, 等等)。例如:
{{ value|filesizeformat }}
django有很多内建的过滤器,我们下一节再讲,因为有30个之多,足以成一节了
标签
标签比变量和过滤器要复杂的多,有些是在输出上产生内容,有些是控制文本流(通过循环和逻辑),还有一些是加载外部的一些内容进入模板
格式:{% tag %}
标签基本都是成对出现的,如:{% tag %} ... tag contents ... {% endtag %}
django内建的标签有很多,接近40个,足以成一节,下下节再说的
注释
注释,不用解释了吧
格式:{# #}
但是这个注释标签只能注释单行的文本
如果你想注释多行的话,要通过comment标签
模板继承
模板系统最有力也是最复杂的部分--模板继承,你可以在父模板中使用block标签定义一些列的变量,然后再字模板中覆盖他们,看下面的例子:
base.html
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>{% block title %}My amazing site{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block content %}{% endblock %} </div> </body> </html>
一个子模板如下,关键是extends标签
{% 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 %}
渲染的效果如下:子模板中有的标签会覆盖父模板的内容如title,子模板没有覆盖的标签将从父模板哪里继承过来,如sidebar
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="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>
下面是一些tips:
- 如果你要使用extends标签,请确保extends在子模板中时第一个标签
- 在父模板中的block标签越多越好
- 如果你在多个子模板中出现了重复的内容,是时候考虑把它们放到父模板里面了
- {{ block.super }} 可以访问父模板中对应block的值,当你仅仅是想在父模板的基础上添加内容而不是覆盖的时候 ,可能会用到这个值
自动HTML转义
威胁主要来自跨站点攻击(XXS)
很明显,用户提交的内容是不能被盲目的信任的,因为一些别有用心的用户可能会利用这种盲目的信任来做一些你意想不到的事情,例如在内容中内嵌了一段javascript代码等等,所以django是默认自动转义的,即是有下面的转换
- < is converted to <
- > is converted to >
- ' (single quote) is converted to '
- " (double quote) is converted to "
- & is converted to &
当从模版中生成HTML时,总会有这样一个风险:值可能会包含影响HTML最终呈现的字符。显然,用户提交的数据都被不应该被盲目的信任,并且被直接插入到你的网页中,因为一个怀有恶意的用户可能会使用这样的漏洞来做一些可能的坏事。这种类型的安全问题被叫做 跨站脚本(Cross Site Scripting) (XSS) 攻击。
默认情况下,Django 中的每个模板会自动转义每个变量的输出。明确地说,下面五个字符被转义:
- < 会转换为<
- > 会转换为>
- ‘(单引号) 会转换为'
- ” (双引号)会转换为 "
- & 会转换为 &
如何关闭它
然而你为什么想要关闭它呢?由于有时,模板变量含有一些你打算渲染成原始HTML的数据,你并不想转义这些内容。例如,你可能会在数据库中储存一些HTML代码,并且直接在模板中嵌入它们。或者,你可能使用Django的模板系统来生成不是HTML的文本 – 比如邮件信息。
提供的几种方法:
- 用于独立变量,使用safe过滤器来关闭独立变量上的自动转义:
his will not be escaped: {{ data|safe }}
- 用于模板代码块,要控制模板上的自动转义,将模板(或者模板中的特定区域)包裹在autoescape标签 中,像这样:
{% autoescape off %}Hello {{ name }}{% endautoescape %}
如果你真的要放弃自动转义,或者你有自己的需要的,或者你确信用户的输入没有威胁的时候,你可以关闭自动HTML转义
在变量中,你可以这样做
This will be escaped: {{ data }} This will not be escaped: {{ data|safe }}
在标签中,你可以这样做
{% autoescape off %} This will not be auto-escaped: {{ data }}. Nor this: {{ other_data }} {% autoescape on %} Auto-escaping applies again: {{ name }} {% endautoescape %} {% endautoescape %}
访问方法调用
在模板中,大多数的方法调用还是可用的,但,方法是不可能在模板中定义的,所有的属性方法必须在模板之前定义好
{% for comment in task.comment_set.all %} {{ comment }} {% endfor %} {{ task.comment_set.all.count }} # In model class Task(models.Model): def foo(self): return "bar" # In template {{ task.foo }}
自定义标签和过滤器库
某些应用提供自定义的标签和过滤器库。要在模板中访问它们,确保应用已经在INSTALLED_APPS 中(在这个例子中我们添加了’django.contrib.humanize’),之后在模板中使用load标签:
{% load humanize %}
{{ 45000|intcomma }}
自定义库和模板继承
当你加载一个自定义标签或过滤器库时,标签或过滤器只在当前模板中有效 – 并不是带有模板继承关系的任何父模板或者子模版中都有效。
例如,如果一个模板foo.html带有{% load humanize %},子模版(例如,带有{% extends “foo.html” %})中不能 访问humanize模板标签和过滤器。子模版需要添加自己的 {% load humanize %}。
这个特性是出于保持可维护性和逻辑性的目的。
参考文章:http://www.cnblogs.com/qwj-sysu/p/4194284.html
http://blog.csdn.net/qq_14898613/article/details/61196500