引言部分
在提到模板之前,来了解网页产生的几种方式:
- html\css语言的网页,以.html为后缀,内容除html\css语法格式外无其他语言
- 以html语言为主体,穿插嵌入别的语言,例如:嵌入javascript
- 以非html语言为主体,html语法以字符串形式穿插在其中,前面Django的视图那节讲述了这种方法
来比较这三种方式的优缺点:
- 第一种方式太死板,所有数据都是硬编码,这种方式被完全抛弃。
- 第二种和第三种都是不错的办法,先看第二种,解决了硬编码的烦恼,但功能太少,因为是以html为主体的,html的专长是显示页面,对数据的处理很乏力,且显示与逻辑混为一体。
- 第三种显然功能最强大,集成了非html语言与html语言于一身;但还是逻辑与显示混为一体。
有没有一种方法,即增强数据处理能力,又能将逻辑与显示区分开来?Django引入了一个解决方案:模板系统。
- Django模板是基于html的文本,以.html为后缀名。html文本中间插入变量(variable)和模板标签(template tag)。当然Django的模板只有Django自己认识。
- Django模板系统将第二种(以html为主体)定义为模板,传给模板系统,模板系统对其进行识别处理,交给浏览器。这就是模板系统的工作原理。简单来讲,还是以python语言为主体,本来html是以普通字符串形式出现改成以整个模板形式出现。模板相比字符串多了很多跟python通讯的手段
模板的语法
- {{ 变量 }}
- {% for item in item_list %} 内容 {% endfor %}
- {% if 条件 %}内容 {% else %}内容{% endif %}
- {{ ship_date|date: "F j, Y" }},过滤器(filter),根据参数”F j, Y"进行格式输出;ship_date是变量,date是过滤器,|管道,”F j, Y"参数
正式开始
使用模板
-) 创建一个Template对象
-) 调用Template对象的render方法,并传入一套变量context。返回字符串,模板中的变量和标签会被context值替换
字典
{'key1':'value1', 'key2':'value2'}
元组
(item1,item2)
几种模板
普通变量
t = Template('I`m {{ name }}') c = Context({'name':'Stephane'}) t.render(c)
元组、一个模板,多个上下文
tuple = ('John', 'Julie', 'Pat') t = Template('I`m {{ name }}') for item in tuple: c = Context({'name':item}) r = render(c)
字典dictionary = {'name':'Sally', 'age':'43'} t = Template('{{ person.name }} is {{person.age}} years old.') c = Context({'person':dictionary}) t.render(c)
对象属性d = datetime.date(1990, 5, 2) t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') c = Context({'date':d}) t.render(c)
对象方法t = Template('{{var}} {{var.upper}} {var.isdigit}} c = Context({'var':'hello'}) t.render(c)
列表list = ['apples', 'bananas', 'carrots'] t = Template('Item 2 is {{items.2}}.') c = Context({'items':list}) t.render(c)
将模板独立出view函数-) 修改setting.py的TEMPLATE_DIRS变量,将模板的路径添加进来TEMPLATE_DIRS = ( '/test/djcode/mysite/templates', )
或TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )
-) 加载模板到view函数中t = get_template('current_datetime.html')#django.template.loader.get_template()
-) 处理模板中的变量c = Context({'current_date': now})
-) 填充模板html = t.render(c)
-) 响应请求return HttpResponse(html)
-) 从加载到响应的一步到位return render_to_response('current_datetime.html', {'current_date': now})#django.shortcuts.render_to_response
-) 模板变量填充的一步到位current_date = datetime.datetime.now() return render_to_response('current_datetime.html',locals())
模板应用的两种高级用法-) 提取公共部分单独制成模板,通过下列方式导入{% include template_name %}
-) 定义可变部分的基础模板供其他模板继承,通过下列方式定义可变部分:{% block tag_name %} {% endblock %}
继承:{% extends "base.html" %}
三层继承法,这种方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作.
- 创建base.html模板,在其定义站点的主要外观感受.这些部分都是不常修改甚至从不修改的部分
- 为网站的每个区域创建base_SECTION.html模板(例如base_photos.html和base_forum.html).这些模板对base.html进行拓展,并包含区域特定的风格与设计.
- 为每种类型的页面创建独立的模板,例如论坛页面或者图片库.这些模板拓展相应的区域模板.
使用模板的一些诀窍
- 如果在模板中使用{% extends %},必须保证其为模板中的第一个模板标记.否则,模板继承将不起作用
- 一般来说,基础模板中的{% block %}标签越多越好.记住,自模板不必定义父模板中所有的代码块,因为你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义.俗话说,钩子越多越好
- 如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个{% block %}中.
- 如果你需要访问父模板中的块的内容,使用{{ block.super }}这个标签吧,这一个魔法变量将会表现出父模板中的内容.如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了.
- 不允许在同一个模板中定义多个同名的{% block %}.存在这样的限制是因为block标签的工作方式是双向的.也就是说,block标签不进挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容.如果模板中出现了两个相同名称的{% block %}标签,父模板将无从得知要使用哪个块的内容.
- {% extends %}对所传入模板名称使用的加载方法和get_template()相同.也就是说,会将模板名称被添加到TEMPLATE_DIRS设置之后.
- 多数情况下,{% extends %}的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量.这使得你能够实现一些很酷的动态功能.