您的位置:首页 > 编程语言 > Go语言

Django学习笔记(5):Django模板系统(下)

2015-05-11 15:16 796 查看
一、Django模板在视图中使用

1.从小的demo开始入手:

上一节,我们使用模板系统,都是在命令行中使用,在实际开发中,我们往往用在视图里。先看一个简单的例子(在djangobook书中的例子,或之前学习笔记中的例子基础上修改)。

1 #coding=utf-8
2 from django.http import HttpResponse
3 import datetime
4 from django.template import Template,Context    #记住导入
5
6 #原先的视图函数
7 #def current_datetime(request):      #[2]
8 #    now=datetime.datetime.now()
9 #    html="<html><body>现在时刻:%s.</body></html>" %now
10 #    return HttpResponse(html)
11
12 #现在使用django模板来修改该视图函数
13 def current_datetime(request):
14     now=datetime.datetime.now()
15     t=Template('<html><body>现在时刻是:{{current_date}}</body></html>')
16     c=Context({'current_date':now})
17     html=t.render(c)
18     return HttpResponse(html)


但是模板仍然嵌套在Python代码里面,我们可以使用django强大的API来从硬盘中载入模板,从而减少调用模板和模板本身的冗余。

2.载入模板

载入模板的流程:
(1):建立模板目录和模板文件,建议在mysite目录下,新建一个templates目录,里面放置模板文件,如.html/.csv等
(2):设置settings.py中的TEMPLATE_DIRS,该设置告诉django的模板加载机制在哪里查找模板。

1 TEMPLATE_DIRS = (
2     '/home/django/mysite/templates',
3 )


1 最好把时区、语言也设置下:
2 #TIME_ZONE = 'America/Chicago'
3 TIME_ZONE = 'CCT'   #时区设置为 China Coastal Time
4
5 #LANGUAGE_CODE = 'en-us'
6 LANGUAGE_CODE = 'zh-cn' #语言设置为中文简体,admin后台显示语言及form表单验证信息提示使用


注意:

  [1]:你可以指定任何目录,只要那个目录下的目录和模板对于你的Web服务器运行时的用户是可读的
如果你找不到一个放置模板的位置,我们推荐你在Django工程目录下创建一个templates目录

  [2]:不要忘了模板目录最后的逗号,Python需要逗号来区分单元素元组和括号括起来的语句,如果你想避免这个错误,可以用列表来替代元组,单元素列表不需要结尾的逗号;元组比列表略微高效,所以我们推荐使用元组

  [3]:使用绝对路径很简单,如果你想更灵活和松耦合,你可利用Django的settings文件是简单的Python代码
这点来动态构建TEMPLATE_DIRS内容,例如:

1 import os.path
2
3 TEMPLATE_DIRS = (
4     os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
5 )


Python内部变量 __file__被自动设置为代码所在的Python模块文件名

3.修改视图函数

1 #coding=utf-8
2 from django.http import HttpResponse
3 import datetime
4 from django.template import Template,Context    #记住导入
5 from django.template.loader import get_template #记得导入
6
7 #原先的视图函数
8 #def current_datetime(request):      #[2]
9 #    now=datetime.datetime.now()
10 #    html="<html><bod
1065e
y>现在时刻:%s.</body></html>" %now
11 #    return HttpResponse(html)
12
13 #使用django模板来修改该视图函数
14 #def current_datetime(request):
15 #    now=datetime.datetime.now()
16 #    t=Template('<html><body>现在时刻是:{{current_date}}</body></html>')
17 #    c=Context({'current_date':now})
18 #    html=t.render(c)
19 #    return HttpResponse(html)
20
21 #现在使用加载模板来修改该视图函数
22 def current_datetime(request):
23     now=datetime.datetime.now()
24     t=get_template('current_datetime.html')
25     c=Context({'current_date':now})
26     html=t.render(c)
27     return HttpResponse(html)


注意:
(1):使用了函数 django.template.loader.get_template().加载模板文件,该get_template()函数以模板名称为参数,在文件系统中找处模块的位置,打开文件并返回一个编译好的Template对象

4.在模板目录下创建模块文件

1 <html><body>It is now {{ current_date }}.</body></html>


创建了current_datetime.html文件,并将视图函数中的now,填充模板变量{{current_date}}.

在我们所有配置完成之后(如:TEMPLATE_DIRS、TIME_ZONE = 'CCT' 、LANGUAGE_CODE = 'zh-cn')等,在浏览器中打开,我们可以看到解析后的页面显示如下:



二、Django高效的工作

1.render_to_response() 优化:

Django提供了一个捷径来使用一行代码完成载入模板,填充Context,渲染模板,返回HttpResponse对象的工作这就是render_to_response(),它在django.shortcuts模块下大部分情况下,你都会使用render_to_response()而不是手动完成上述的事情

1 from django.shortcuts import render_to_response #import
2 import datetime
3
4 #使用render_to_response优化处理
5 def current_datetime(request):
6     now=datetime.datetime.now()
7     return render_to_response('current_datetime.html',{"current_date":now})


(1):我们不在import get_template,Template,Context或者HttpResponse相反,我们import django.shortcuts.render_to_response,import datetime仍然存在.

(2):render_to_response()的第一个参数应该是使用的模板名,对应到模板目录的相对路径,第二个参数如果有的话应该是一个用来创建Context的字典,如果不提供第二个参数,render_to_response()将使用一个空的字典。

(3):render_to_response返回HttpResponse对象,所以我们return之。

2.locals()小技巧

像上面的,计算一些值后存储在变量中(例如now)并传递给模板懒程序员可能会觉得有点繁琐,既要给临时变量取名又要给模板变量取名这不仅仅是冗余,这是过度输入如果你很懒或者你想保持代码整洁,使用Python内建的locals()方法

locals()返回一个包含当前作用域里面的所有变量和它们的值的字典,上面的代码可以重写:

1 def current_datetime(request):
2 #  now=datetime.datetime.now()
3     current_date=datetime.datetime.now()
4     return render_to_response('current_datetime.html',locals())


这里我们传递locals()的值而不是手动指定context字典,locals()包含了所有定义在当前方法的变量而且,我们把now变量重命名为current_date,因为模板需要的是这个变量名这个例子中locals()不会给你太大改善,但这个技术可以帮你少敲键盘。
使用locals()需要注意的是它包含了所有当前变量,可能包括比你的模板想访问的更多的变量上面的例子中,locals()也包括request变量,这依赖于你的程序。
最后要注意的是locals()导致了一点点开销,因为Python不得不动态创建字典,如果你手动指定context字典则可以避免这项开销。

3.get_template()中使用子目录

把所有模板放在一个目录下可能会让事情变得难以掌握,推荐把一些模板放在模板目录下的子目录里,如果我们方法,则只需要调用get_template()时,在模板名前面添加子目录名和斜线即可,如下:

1 def current_datetime(request):
2     current_date=datetime.datetime.now()
3 #  t=get_template("date/current_datetime.html")
4     return render_to_response('date/current_datetime.html',locals())


注意:

(1):由于render_to_response()只是对get_template()的简单封装,可以对render_to_response的第一个参数做同样的处理。

(2):对于子目录树的深度没有限制

4.include模板标签

我们已经学习了模板载入机制,我们要介绍一个利用这个机制的内建标签:{% include %}
这个标签允许你引入另一个模板的内容,标签的参数是你想引入的模板的名字,名字可以是变量,也可以是单引号或双引号表示的string。

单双引号都可:

1 {% include 'nav.html' %}
2 {% include "nav.html" %}


下面的例子引入了includes/nav.html模板:

1 {% include 'includes/nav.html' %}


下面的例子引入了一个名字存在于template_name变量中的模板:

1 {% include template_name %}


和get_template()一样,请求的模板名前面会加上TEMPLATE_DIRS,在settings.py 中之前已经设置了:

1 TEMPLATE_DIRS = (
2     os.path.join(os.path.dirname(__file__),'templates').replace('\\','/'),
3 )


则,include引用模板必须在该目录下,如templates目录下,这里我们引入hello.html

1 <h3> Is is now {{current_date}}</h3>
2 <h2 style="color:#F00">{%include "hello.html"%}</h2>


hello.html仅仅是一段字符串,如下:

1 <p>aaa</p>


则,在浏览器中输出:



注意:

如果被引入的模板中包含任何的模板代码,如标签和变量等,它将用父模板的context计算它们
如果给定的模板名不存在,Django将做下面两件事情中的一件:
(1):如果DEBUG设置为True,你将看到一个TemplateDoesNotExist异常的错误页面
(2):如果DEBUG设置为False,标签将什么也不显示

三、模板的继承

我们在使用include的时候,发现很有局限性,Django的模板继承很好地解决了这个问题。流程如下:
1.第一步是建立基本模板(如base.html),即你的子模板的框架

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>{%block title %}{%endblock%}</title>
6 </head>
7
8 <body>
9 <h1>Django--BeginMan</h1>
10 {%block content%}{%endblock%}
11 {%block footer%}
12 <hr />
13 <p style='color:#ccc'>Thanks for visiting my site</p>
14 {%endblock%}
15 </body>
16 </html>


这是一个主模板(基础模板),其他子模板的作用就是重载、继承、添加那些块的内容,{%block%}告诉模板引擎。子模块可以重载这部分。

2.第二步建立子模板

1 ----对current_datetime.html进行修改:
2 <body>
3 {%extends "base.html"%}
4 {%block title%}当前时间{% endblock %}
5 {%block content%}
6     <h3> Is is now {{current_date}}</h3>
7
8 {%endblock%}
9 </body>
10 </html>


1 --------对hello.html进行修改
2 <body>
3 {%extends "base.html"%} <!--第一个模板标记,即以它开头,否则模板继承将不起作用-->
4 {%block title%}HelloWorld{%endblock%}
5 {%block content%}
6     aaa
7 {%endblock%}
8 </body>


在浏览器中显示效果如下:



[current_datetime.html]



[hello.html]

注意:
(1):{%extends %} 不需要关闭标签,它只是单个出现。当出现{%extends "base.html"%}时,模板引擎会立即装载其父模板。
(2):{%block%}是成对出现的,使用过程中要以{%endblock%}关闭,当遇到{%block%}的时候,用子模板的内容替换这些block。

(3):可使用任意等级的继承,使用继承的常用方式是按以下三个步骤:
  [1]:创建base.html模板来掌控你的网站的整体外观,它的内容很少改变
  [2]:为你的网站创建base_SECTION.html模板,例如,base_photos.html,base_forum.html这些模板继承base.html并且包括部分专有的风格和设计
  [3]:为每个类别的页面创建单独的模板,例如论坛页面或照片图库页面,这些模板拓展相应的模板区域

3、关于模板继承的小提示:
1,如果在模板里使用{% extends %}的话,这个标签必须在所有模板标签的最前面,否则模板继承不工作
2,通常基本模板里的{% block %}越多越好,子模板不必定义所有的父block,钩子越多越好
3,如果你在很多模板里复制代码,很可能你应该把这些代码移动到父模板里
4,如果你需要得到父模板的块内容,{{ block.super }}变量可以帮你完成工作
当你需要给父块添加内容而不是取代它的时候这就很有用
5,不能在同一模板里定义多个同名的{% block %},因为块标签同时在两个地方工作,不仅仅
在子模板中,而且在父模板中也填充内容,如果子模板有两个同名的标签,父模板将不能决定
使用哪个块内容来使用
6,你给{% extends %}传递的模板名同样会被get_template()使用,所以会加上TEMPLATE_DIRS设置
7,大部分情况下,{% extends %}的参数是string,但是也可以是变量,如果知道运行时才知道
父模板的名字,这可以帮助你做一些很cool的动态内容

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: