上一篇中带参数的URLconf虽然可以做到传参动态显示内容,但是最终现实的内容还是硬编码到Python代码中的
1 def hours_ahead(request,phours): 2 try: 3 phours = int(phours) 4 except VauleError: 5 raise Http404() 6 7 dt = datetime.datetime.now() + datetime.timedelta(hours=phours) 8 html = "<html><body>In %s hour(s),it will be %s.</body></html>" % (phours,dt) 9 return HttpResponse(html)
这种方式的坏处我就不多说了。
将页面的设计和Python的代码分离开,让系统更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式。
模板系统基本知识
模板是一个文本,用于分离文档的表现形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。 模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。
先看一个例子
1 <html> 2 <head><title>Ordering notice</title></head> 3 4 <body> 5 6 <h1>Ordering notice</h1> 7 8 <p>Dear {{ person_name }},</p> 9 10 <p>Thanks for placing an order from {{ company }}. It‘s scheduled to 11 ship on {{ ship_date|date:"F j, Y" }}.</p> 12 13 <p>Here are the items you‘ve ordered:</p> 14 15 <ul> 16 {% for item in item_list %} 17 <li>{{ item }}</li> 18 {% endfor %} 19 </ul> 20 21 {% if ordered_warranty %} 22 <p>Your warranty information will be included in the packaging.</p> 23 {% else %} 24 <p>You didn‘t order a warranty, so you‘re on your own when 25 the products inevitably stop working.</p> 26 {% endif %} 27 28 <p>Sincerely,<br />{{ company }}</p> 29 30 </body> 31 </html>
该模板是一段添加了些许变量和模板标签的基础 HTML 。 让我们逐步分析一下:
- 用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。这意味着在此处插入指定变量的值。
- 被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。标签(tag)定义比较明确,即: 仅通知模板系统完成某些工作的标签。
- 最后,这个模板的第二段中有一个关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。 如这个例子中的{{ship_date|date:”F j, Y” }},我们将变量ship_date传递给date过滤器,同时指定参数”F j,Y”。date过滤器根据参数进行格式输出。 过滤器是用管道符(|)来调用的(目前我也不了解,本文不涉及该具体内容)
如何使用模板系统
在Python代码中使用Django模板的最基本方式如下:
- 可以用原始的模板代码字符串创建一个 Template 对象, Django同样支持用指定模板文件路径的方式来创建Template 对象。
- 调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展现字符串,模板中的变量和标签会被context值替换。
1 from django import template 2 t = template.Template(‘My name is {{ name }}.‘) 3 c = template.Context({‘name‘: ‘Adrian‘}) 4 print t.render(c) 5 #My name is Adrian. 6 c = template.Context({‘name‘: ‘Fred‘}) 7 print t.render(c) 8 #My name is Fred.
注意:在运行该段代码时,请使用 python manage.py shell。
为什么我们运行python manage.py shell而不是python?
这两个命令都会启动交互解释器,但是manage.py shell命令有一个重要的不同: 在启动解释器之前,它告诉Django使用哪个设置文件。 Django框架的大部分子系统,包括模板系统,都依赖于配置文件;如果Django不知道使用哪个配置文件,这些系统将不能工作。
模板渲染
一旦你创建一个 Template 对象,你可以用 context 来传递数据给它。 一个context是一系列变量和它们值的集合。context在Django里表现为 Context 类,在 django.template 模块里。 她的构造函数带有一个可选的参数: 一个字典映射变量和它们的值。调用 Template 对象 的 render() 方法并传递context来填充模板:
1 >>> from django.template import Context, Template 2 >>> t = Template(‘My name is {{ name }}.‘) 3 >>> c = Context({‘name‘: ‘Stephane‘}) 4 >>> t.render(c) 5 u‘My name is Stephane.‘
t.render(c)返回的值是一个Unicode对象,不是普通的Python字符串。 你可以通过字符串前的u来区分。 在框架中,Django会一直使用Unicode对象而不是普通的字符串。
同一模板,多个上下文
1 t = Template(‘Hello, {{ name }}‘) 2 for name in (‘John‘, ‘Julie‘, ‘Pat‘): 3 print t.render(Context({‘name‘: name}))
深度变量的查找
模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。
访问字典的值
1 >>> from django.template import Template, Context 2 >>> person = {‘name‘: ‘Sally‘, ‘age‘: ‘43‘} 3 >>> t = Template(‘{{ person.name }} is {{ person.age }} years old.‘) 4 >>> c = Context({‘person‘: person}) 5 >>> t.render(c) 6 u‘Sally is 43 years old.‘
访问类型的属性(适用于任意自定义类型的属性)
1 >>> from django.template import Template, Context 2 >>> import datetime 3 >>> d = datetime.date(1993, 5, 2) 4 5 >>> t = Template(‘The month is {{ date.month }} and the year is {{ date.year }}.‘) 6 >>> c = Context({‘date‘: d}) 7 >>> t.render(c) 8 u‘The month is 5 and the year is 1993.‘
点语法也可以用来引用对象的 方法。 例如,每个 Python 字符串都有 upper() 和 isdigit() 方法,你在模板中可以使用同样的句点语法来调用它们:
1 >>> from django.template import Template, Context 2 >>> t = Template(‘{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}‘) 3 >>> t.render(Context({‘var‘: ‘hello‘})) 4 u‘hello -- HELLO -- False‘ 5 >>> t.render(Context({‘var‘: ‘123‘})) 6 u‘123 -- 123 -- True‘
注意:这里调用方法时并没有使用圆括号,而且也无法给该方法传递参数,你只能调用不需参数的方法。
最后,句点也可用于访问列表索引,例如:
1 >>> from django.template import Template, Context 2 >>> t = Template(‘Item 2 is {{ items.2 }}.‘) 3 >>> c = Context({‘items‘: [‘apples‘, ‘bananas‘, ‘carrots‘]}) 4 >>> t.render(c) 5 u‘Item 2 is carrots.‘
注意:不允许使用负数列表索引。 像 {{ items.-1 }} 这样的模板变量将会引发"TemplateSyntaxError"
句点查找规则可概括为: 当模板系统在变量名中遇到点时,按照以下顺序尝试进行查找:
- 字典类型查找 (比如 foo["bar"] )
- 属性查找 (比如 foo.bar )
- 方法调用(比如 foo.bar() )
- 列表类型索引查找 (比如 foo[bar] )
系统使用找到的第一个有效类型。 这是一种短路逻辑。
处理无效变量
默认情况下,如果一个变量不存在,模板系统会把它展示为空字符串,不做任何事情来表示失败。
1 >>> from django.template import Template, Context 2 >>> t = Template(‘Your name is {{ name }}.‘) 3 >>> t.render(Context()) 4 u‘Your name is .‘ 5 >>> t.render(Context({‘var‘: ‘hello‘})) 6 u‘Your name is .‘ 7 >>> t.render(Context({‘NAME‘: ‘hello‘})) 8 u‘Your name is .‘ 9 >>> t.render(Context({‘Name‘: ‘hello‘})) 10 u‘Your name is .‘
变量是区分大小写的。
小结
使用Django模板系统的基本规则: 写模板,创建 Template 对象,创建 Context , 调用 render() 方法。
使用 python manage.py shell 启动交互式解释器,自动加载相关环境配置信息
点(.)操作