模板的应用原理、过程
以mysite项目为例:
当一个url开始匹配开始时,先去mysite/mysite/urls.py 里匹配,然后里面会具体匹配到哪个应用,调用相应应用下的urls.py,(例如这里是polls)-> mysite/mysite/polls/urls.py 里面匹配到相应的url后,会调用polls应用下views.py里相应的函数 -> mysite/mysite/polls/views.py 最后使用render或render_to_response输出相应的模板 -> mysite/mysite/polls/templates/polls/template.html
如果这个模板还通过include引用了其他页面,或继承于其他模板页面,会继续加载相应的页面或模板
模板的配置方法
1、先在项目/setting.py下配置添加模板路径
setting.py内TEMPLATES 设置中添加一个DIRS 选项 :
'DIRS': [os.path.join(BASE_DIR, 'templates')],
其中BASE_DIR =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
然后再在相应应用下面建立模板目录,放置模板文件,最终结构是templates/应用名称(例如polls)/模板文件(index.html等) ,使用时系统会自动查找templates目录,注意是templates目录,要自行加上plls路径,不然会找不到文件
模板中的注释
l 单行:{# This is acomment #}
l 多行:要使用标签了
{% comment %}
This is a
multi‐line comment.
{% endcomment %}
过滤器
模板过滤器是在变量被显示前修改它的值的一个简单方法。过滤器使用管道字符。
例1:小写转换
{{ name|lower }}
显示的内容是变量 ` name ` 被过滤器 lower 处理后的结果,它功能是转换文本为小写。
例2:日期格式化显示
{{ pub_date|date:"F j, Y" }}
例3:
{{ bio|truncatewords:"30" }}
这个将显示变量 bio 的前30个词。
基本的模板标签
include标签
内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。
例:
{% include ‘polls/foot.html’%}
if/else标签
标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会
显示在 {% if %} 和 {% endif %} 之间的任何内容
例:
{% if today_is_weekend %}
<p>Welcome to theweekend!</p>
{% endif %}
{% else %} 标签是可选的:
{% if today_is_weekend %}
<p>Welcome to theweekend!</p>
{% else %}
<p>Get back to work.</p>
{% endif %}
注意:
1、在Python和Django模板系统中,以下这些对象相当于布尔值的False,其余的都是True
l 空列表([] )
l 空元组(() )
l 空字典({} )
l 空字符串('' )
l 零值(0 )
l 特殊对象None
l 对象False(很明显)
2、{% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的
例:{% ifathlete_list and coach_list or cheerleader_list %} 这是错误的
3、系统不支持用圆括号来组合比较操作。如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板
之外处理,然后以模板变量的形式传入结果吧。或者,仅仅用嵌套的{% if %}标签替换吧,就像这样:
{% if athlete_list %}
{% if coach_list orcheerleader_list %}
We have athletes,and either coaches or cheerleaders!
{ % endif %}
{% endif %}
4、多次使用同一个逻辑操作符是没有问题的,但是我们不能把不同的操作符组合起来。例如,这是合法的:
{% if athlete_list or coach_list or parent_list or teacher_list %}
5、没有 {% elif %} 标签,并且一定要用 {% endif %} 关闭每一个 {% if %} 标签。
for标签
{%for %} 允许我们在一个序列上迭代。 与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定的循环中使用的变量名称。 每一次循环中,模板系统会渲染在 {% for%} 和{%endfor %} 之间的所有内容。
例:
{% for athlete in athlete_list %}
<li>`athlete`.`name `</li>
{% endfor %}
在执行循环之前先检测列表的大小是一个通常的做法,当列表为空时输出一些特别的提示。
{%if athlete_list %}
{% for athlete in athlete_list %}
<p>` athlete`.`name`</p>
{% endfor %}
{%else %}
<p>There are no athletes. Only computerprogrammers.</p>
{%endif %}
for标签里有很多变量,方便我们的使用。在每个``{% for %}``循环里有一个称为`` forloop`` 的模板变量。这个变量有一些提示循环进度信息的属性。
l forloop.counter 总是一个表示当前循环的执行次数的整数计数器。这个计数器是从1开始的,所以在第一
次循环时forloop.counter 将会被设置为1。
例:结果会显示1 2 3
y=[1,2,3]
{%for x in y %}
`forloop`.`counter `
{%endfor %}
l forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。第一次执行循环时这个变量会被设置
为0。
l forloop.revcounter 是表示循环中剩余项的整型变量。在循环初次执行时 forloop.revcounter 将被设置
为序列中项的总数。最后一次循环执行中,这个变量将被置1。
l forloop.revcounter0 类似于 forloop.revcounter,但它以0做为结束索引。在第一次执行循环时,该变
量会被置为序列的项的个数减1。
l forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为````
l forloop.last 是一个布尔值;在最后一次执行循环时被置为True
l forloop.parentloop 是一个指向当前循环的上一级循环的forloop对象的引用(在嵌套循环的情况下)。
例:
{%for country in countries %}
<table>
{%for city in country.city_list %}
<tr>
<td>Country#` forloop`.`parentloop`.`counter `</td>
<td>City#` forloop`.`counter `</td>
<td>`city `</td>
</tr>
{%endfor %}
</table>
{%endfor %}
注意:
l Django不支持退出循环操作。 如果我们想退出循环,可以改变正在迭代的变量,让其仅仅包含需要迭代的项目。同理,Django也不支持continue语句,我们无法让当前迭代操作跳回到循环头部。
l forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了
ifequal/ifnotequal标签
{%ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。
例:比较两个模板变量 user 和 currentuser :
{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}
参数可以是硬编码的字符串,随便用单引号或者双引号引起来,所以下列代码都是正确的:
{% ifequal section 'sitenews' %}
<h1>SiteNews</h1>
{% endifequal %}
和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签:
{% ifequal section 'sitenews' %}
<h1>SiteNews</h1>
{% else %}
<h1>NoNews Here</h1>
{% endifequal %}
注意:
l 只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数。下面是合法参数的例子:
{% ifequal variable 1 %}
{% ifequal variable 1.23 %}
{% ifequal variable 'foo' %}
{% ifequal variable"foo" %}
l 其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在 {% ifequal %} 中。 下面是些错误的
例:
{% ifequal variable True %}
{% ifequal variable [1, 2, 3]%}
{% ifequal variable {'key':'value'} %}
l 如果你需要判断变量是真还是假,请使用 {% if %} 来替代 {% ifequal %}
模板继承
为了减少开发中代码的书写,除了使用{% include %}共用的代码,更好的方法就是模板继承
模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。
使用方法:第一步是定义继承模板,一个基本的html页面,页面中{% block blockname %} 内容 {% endblock %} 里的内容就是可以重载、添加或保留的那些块。当一个页面继承了所定义的模板,它可以选择自定义{% block blockname %} {% endblock %}之间的内容,如果不去改变就会沿用原有设置
例(在视图中使用模板):
1、先定义一个模板base.html
<!DOCTYPEHTML PUBLIC "‐//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>{%block title %}标题内容{% endblock %}</title>
</head>
<body>
{%block content %}内容<h1>My helpful timestamp site</h1>{% endblock %}
{%block footer %}
<hr>
<p>Thanksfor visiting my site.页脚</p>
{%endblock %}
</body>
</html>
2、然后在extends.html页面中继承base.html
{%extends "polls/base.html" %} #这里的路径要注意!django只会查找每个应用的templates根目录,再下一层的目录要手动写上去
{%block title %} dx site {% endblock %}
{%block content %} <h2> dx content </h2> {% endblock %}
3、然后在polls应用下的view.py 定义一个用于测试继承的函数
defextends_test(request):
returnrender_to_response('polls/extends.html')
4、再在polls应用下的url.py定义一个新的url匹配规则
#ex: /polls/extends/
url(r'extends/$', views.extends_test, name='extends_test'),
至此,模板的继承应用就实现了
注意:
l 如果在模板中使用 {%extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作
用。
l {% extends %} 对所传入模板名称使用的加载方法和 get_template() 相同。 也就是说,会将模板名称被添
加到 TEMPLATE_DIRS 设置之后。
l 多数情况下, {%extends %} 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也
可以是个变量。 这使得你能够实现一些很酷的动态功能
其他技巧
当我们利用render或render_to_response调用模板输出的时候,可以利用locals()传入所有的局部变量到模板里,这样就可以偷懒写一个locals()就可以了。