Django模板系统 非常详细

               

转载:http://www.czug.org/python/django/04.html


翻译www.djangobook.com之第四章:Django模板系统

The Django Book:第4章 Django模板系统

revised by xin_wang

前面的章节我们看到如何在视图中返回HTML,但是HTML是硬编码在Python代码中的
这会导致几个问题:
1,显然,任何页面的改动会牵扯到Python代码的改动
网站的设计改动会比Python代码改动更频繁,所以如果我们将两者分离开会更方便
2,其次,写后台Python代码与设计HTML是不同的工作,更专业的Web开发应该将两者分开
页面设计者和HTML/CSS程序员不应该编辑Python代码,他们应该与HTML打交道
3,程序员写Python代码同时页面设计者写HTML模板会更高效,而不是一个人等待另一个人编辑同样的文件
因此,使用Django的模板系统分离设计和Python代码会更干净更易维护

模板系统基础
Django模板是一个string文本,它用来分离一个文档的展现和数据
模板定义了placeholder和表示多种逻辑的tags来规定文档如何展现
通常模板用来输出HTML,但是Django模板也能生成其它基于文本的形式
让我们来看看一个简单的模板例子:
<html><head><title>Ordering notice</title></head><body><p>Dear {
    { person_name }},</p><p>Thanks for placing an order from {
    { company }}. It's scheduled toship on {
     { ship_date|date:"F j, Y" }}.</p><p>Here are the items you've ordered:</p><ul>{% for item in item_list %}<li>{
    { item }}</li>{% endfor %}</ul>{% if ordered_warranty %}<p>Your warranty information will be included in the packaging.</p>{% endif %}<p>Sincerely,<br />{
    { company }}</p></body></html>

这个模板本质上是HTML,但是夹杂了一些变量和模板标签:
1,用{ {}}包围的是变量,如{ {person_name}},这表示把给定变量的值插入,如何指定这些变量的值我们即将说明
2,用{%%}包围的是块标签,如{%if ordered_warranty%}
块标签的含义很丰富,它告诉模板系统做一些事情
在这个例子模板中包含两个块标签:for标签表现为一个简单的循环结构,让你按顺序遍历每条数据
if标签则表现为逻辑的if语句
在这里,上面的标签检查ordered_warranty变量的值是否为True
如果是True,模板系统会显示{%if ordered_warranty%}和{%endif%}之间的内容
否则,模板系统不会显示这些内容
模板系统也支持{%else%}等其它逻辑语句
3,上面还有一个过滤器的例子,过滤器是改变变量显示的方式
上面的例子中{ {ship_date|date:"F j, Y"}}把ship_date变量传递给过滤器
并给date过滤器传递了一个参数“F j, Y”,date过滤器以给定参数的形式格式化日期
类似于Unix,过滤器使用管道字符“|”
Django模板支持多种内建的块标签,并且你可以写你自己的标签

使用模板系统
在Python代码中使用模板系统,请按照下面的步骤:
1,用模板代码创建一个Template对象
Django也提供指定模板文件路径的方式创建Template对象
2,使用一些给定变量 context调用Template对象的render()方法
这将返回一个完全渲染的模板,它是一个string,其中所有的变量和块标签都会根据context得到值

创建模板对象
最简单的方式是直接初始化它,Template类在django.template模块中,初始化方法需要一个参数
下面进入Python交互环境看看:
>>> from django.template import Template>>> t = Template("My name is {
     {my_name}}.")>>> print t

你将看到如下信息
<django.template.Template object at 0xb7d5f24c>

0xb7d5f24c每次都会改变,但是无所谓,它是Template对象的Python“identity”
在这本书中,我们会在Python的交互式会话环境中展示一些示例。当你看到三个大于号'>>>',就可以确定是在交互环境中了。
如果你从本书中拷贝代码,记得不要拷贝这些大于号。
当你创建Template对象,模板系统会编译模板代码,并准备渲染
如果你的模板代码有语法错误,调用Template()方法会触发TemplateSyntaxError异常
>>> from django.template import Template>>> t = Template('{%notatag%}')Traceback (most recent call last):    File "<stdin>", line 1, in ?    ...   django.template.TemplateSyntaxError: Invalid block tag: 'notatag'

系统触发TemplateSyntaxError异常可能出于以下情况:
1,不合法的块标签
2,合法块标签接受不合法的参数
3,不合法的过滤器
4,合法过滤器接受不合法的参数
5,不合法的模板语法
6,块标签没关

渲染模板
一旦你拥有一个Template对象,你可以通过给一个context来给它传递数据
context是一个变量及赋予的值的集合,模板使用它来得到变量的值,或者对于块标签求值
这个context由django.template模块的Context类表示
它的初始化函数有一个可选的参数:一个映射变量名和变量值的字典
通过context调用Template对象的render()方法来填充模板,例如:
>>> from django.template import Context, Template>>> t = Template("My name is {
     {name}}.")>>> c = Context({
    "name": "Stephane"})>>> t.render(c)'My name is Stephane.'

变量名必须以字母(A-Z或a-z)开始,可以包含数字,下划线和小数点,变量名大小写敏感
下面是一个模板编译和渲染的例子,使用这章开始时的模板例子:
>>> from django.template import Template, Context>>> raw_template = """<p>Dear {
     { person_name }},</p>...... <p>Thanks for ordering {
     { product }} from {
     { company }}. It's scheduled to... ship on {
     { ship_date|date:"F j, Y" }}.</p>...... {% if ordered_warranty %}... <p>Your warranty information will be included in the packaging.</p>... {% endif %}...... <p>Sincerely,<br />{
     { company }}</p>""">>> t = Template(raw_template)>>> import datetime>>> c = Context({
    'person_name': 'John Smith',...     'product': 'Super Lawn Mower',...     'company': 'Outdoor Equipment',...     'ship_date': datetime.date(2009, 4, 2),...     'ordered_warranty': True})>>> t.render(c)"<p>Dear John Smith,</p>\n\n<p>Thanks for ordering Super Lawn Mower from Outdoor Equipment.It's scheduled to ship on April 2, 2009.</p>\n\n<p>Your warranty information will be includedin the packaging.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment</p>"

让我们来看看都做了些什么:
1,我们import Template和Context类,它们都在django.template模块里面
2,我们把模板文本存储在raw_template变量里,我们使用"""来构建string,它可以跨越多行
3,我们创建模板对象t,并给Template类的初始化函数传递raw_template变量
4,我们从Python的标准库import datetime模块,下面会用到它
5,我们创建一个context对象c,它的初始化函数使用一个映射变量名和变量值的字典
例如我们指定person_name的值为'John Smith',product的值为'Super Lawn Mower'等等
6,最后,我们调用模板对象的render()方法,参数为context对象c
这将返回渲染后的模板,将模板中的变量值替换并计算块标签的结果
如果你刚接触Python,你可能会问为什么输出中包含了新行字符'\n'而不是换行
这是因为Python交互环境中调用t.render(c)会显示string的representation而不是string的值
如果你想看到换行而不是'\n',使用print t.render(c)即可
上面是使用Django模板系统的基础,只是创建一个模板对象和context对象然后调用render()方法
同一个模板,多个context的情况:
一旦你创建了一个模板对象,你可以渲染多个context,例如:
>>> from django.template import Template, Context>>> t = Template('Hello, {
     { name }}')>>> print t.render(Context({
    'name': 'John'}))Hello, John>>> print t.render(Context({
    'name': 'Julie'}))Hello, Julie>>> print t.render(Context({
    'name': 'Pat'}))Hello, Pat

无论何时,你使用同一个模板来渲染多个context的话,创建一次Template对象然后调用render()多次会更高效
# Badfor name in ('John', 'Julie', 'Pat'):    t = Template('Hello, {
     { name }}')    print t.render(Context({
    'name': name}))# Goodt = Template('Hello, {
     { name }}')for name in ('John', 'Julie', 'Pat'):    print t.render(Context({
      'name': name}))

Django的模板解析非常快,在后台,大部分的解析通过一个单独的对正则表达式的调用来做
这与基于XML的模板引擎形成鲜明对比,XML解析器比Django的模板渲染系统慢很多

Context变量查找
上面的例子中,我们给模板context传递了简单的值,大部分是string,以及一个datetime.date
尽管如此,模板系统优雅的处理更复杂的数据结构,如列表,字典和自定义对象
在Django模板系统中处理复杂数据结构的关键是使用(.)字符
使用小数点来得到字典的key,属性,对象的索引和方法
下面通过例子来解释,通过(.)访问字典的key:
>>> from django.template import Template, Context>>> person = {
    'name': 'Sally', 'age': '43'}>>> t = Template('{
     { person.name }} is {
     { person.age }} years old.')>>> c= Context({
    'person': person})>>> t.render(c)'Sally is 43 years old.'

通过(.)来访问对象的属性:
>>> from django.template import Template, Context>>> import datetime>>> d = datetime.date(1993, 5, 2)>>> d.year1993>>> d.month5>>> d.day2>>> t = Template('The month is {
     { date.month }} and the year is {
     { date.year }}.')>>> c = Context({
    'date': d})>>> t.render(c)'The month is 5 and the year is 1993.'

下面的例子使用一个自定义类:
>>> from django.template import Template, Context>>> class Person(object):...    def __init__(self, first_name, last_name):...        self.first_name, self.last_name = first_name, last_name>>> t = Template('Hello, {
     { person.first_name }} {
     { person.last_name }}.')>>> c = Context({
    'person': Person('John', 'Smith')})>>> t.render(c)'Hello, John Smith.'

小数点也可以用来调用列表的索引:
>>> from django.templat
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值