Django模板引擎的研究

原创博文,转载请注明出处。

以前曾遇到过错误Reverse for ‘*’ with arguments '()' and keyword arguments' not found.1其原因是没有给视图函数传入参数。解决方法传入参数即可。

可是今天又遇到了同样的问题,发现原来的方法不好使了。研究了一下午,我发现原来在我的模板文件中,有多个视图函数需要传入同一名称的参数。如果不能明白我所表达的意思可以见下图

可以看到在blog.urls 所对应的视图函数必定需要一个参数realid,这就带来了多个视图函数需要传入同一名称的参数的问题。

问题的解决是我无意间把context_instance=RequestContext(request)去掉换成locals()。

所以,我决定把模板引擎进行一番学习。出自Django book

1、基本知识:模板是一个文本,用于分离文档的表现形式和内容。模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签)。模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。我们通常将模板和视图一起使用(实际,不限于此)。

2、最简单的模板系统实现方法:

(1)创建一个Template对象,Django支持用知道模板文件路径的方式来创建Template对象。

(2)模板渲染:调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展示字符串,模板中的变量和标签会被context指替换。

context是一系列变量和它们值得集合。

总结起来就是:写模板,创建Template对象,创建Context,调用render()方法。示例如下:

 1 >>> from django.template import Template, Context
2 >>> raw_template = """<p>Dear {{ person_name }},</p>
3 ...
4 ... <p>Thanks for ordering {{ product }} from {{ company }}. It's scheduled
5 ... to ship on {{ ship_date|date:"F j, Y" }}.</p>
6 ...
7 ... {% if ordered_warranty %}
8 ... <p>Your warranty information will be included in the packaging.</p>
9 ... {% endif %}
10 ...
11 ... <p>Sincerely,<br />{{ company }}</p>"""
12 >>> t = Template(raw_template) 实例化Template对象
13 >>> import datetime
14 >>> c = Context({'person_name': 'John Smith', 实例化context对象
15 ... 'product': 'Super Lawn Mower',
16 ... 'company': 'Outdoor Equipment',
17 ... 'ship_date': datetime.date(2009, 4, 2),
18 ... 'ordered_warranty': True})
19 >>> t.render(c) 调用render方法
20 "<p>Dear John Smith,</p>\n\n<p>Thanks for ordering Super Lawn Mower from
21 Outdoor Equipment. It's scheduled \nto ship on April 2, 2009.</p>\n\n\n
22 <p>Your warranty information will be included in the packaging.</p>\n\n\n
23 <p>Sincerely,<br />Outdoor Equipment</p>"

django.template.Template类构造函数接受一个参数,原始模板代码。

django.template.Context类的构造函数带有一个可选的参数:一个字典变量和它们的值。

可以看到输出中,模板对象中的‘person_name’被替换成了‘john Smith’,‘product’被替换成了‘Super Lawn Mower’等等。

3、强大的模板加载:可以从磁盘中加载模板,也就是说我们实现了视图函数和模板文件的分离。让它使用 Django 模板加载功能而不是对模板路径硬编码。

首先我们必须设置settings.py里面的TEMPLATE_DIRS,将模板的保存位置告诉框架。这里我们介绍一种使用相对路径的方法

import os.path

TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
os.path.dirname(__file__)将会获取自身所在的文件,即settings.py 所在目录,然后由os.path.join这个方法将这目录与templates进行连接。前提是我们需要创建一个templates文件夹来存放模板文件
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime def current_datetime(request):
now = datetime.datetime.now()
t = get_template('current_datetime.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)

此范例中,我们使用了函数 django.template.loader.get_template() ,而不是手动从文件系统加载模板。该 get_template() 函数以模板名称为参数,在文件系统中找出模块的位置,打开文件并返回一个编译好的 Template 对象。如果 get_template() 找不到给定名称的模板,将会引发一个 TemplateDoesNotExist 异常。

render_to_response()

由于加载模板、填充 context 、将经解析的模板结果返回为 HttpResponse 对象这一系列操作实在太常用了,Django 提供了一条仅用一行代码就完成所有这些工作的捷径。该捷径就是位于 django.shortcuts 模块中名为 render_to_response() 的函数。大多数时候,你将使用 render_to_response() ,而不是手动加载模板、创建 Context 和 HttpResponse 对象。

from django.shortcuts import render_to_response
import datetime def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})

render_to_response() 的第一个参数必须是要使用的模板名称。如果要给定第二个参数,那么该参数必须是为该模板创建Context 时所使用的字典。如果不提供第二个参数, render_to_response() 使用一个空字典。

Python 的内建函数 locals() 。它返回的字典对所有局部变量的名称与值进行映射。这可给你省了不少事情,但前提必须是变量的名称和模板文件被替换的值必须一致。因此,我们将 now 变量重命名为 current_date 。

def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())

同时,locals() 还包含了 request 。

RequestContext和Context处理器

RequestContext 默认地在模板context中加入了一些变量,如 HttpRequest 对象或当前登录用户的相关信息。

当你不想在一系例模板中都明确指定一些相同的变量时,你应该使用 RequestContext 。Context处理器允许你设置一些变量,它们会在每个context中自动被设置好,而不必每次调用 render_to_response() 时都指定。要点就是,当你渲染模板时,你要用 RequestContext 而不是 Context 。

建议选择 render_to_response() 作为context的处理器。像这样,使用 context_instance 参数,调用processors:

from django.shortcuts import render_to_response
from django.template import RequestContext def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
} def view_1(request):
# ...
return render_to_response('template1.html',
{'message': 'I am view 1.'},
context_instance=RequestContext(request, processors=[custom_proc])) def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, processors=[custom_proc])) def view_3(request):
# ...
return render_to_response('template3.html',
{'message': 'I am the third view.'},
context_instance=RequestContext(request, processors=[custom_proc])) def view_4(request):
# ...
return render_to_response('template4.html',
{'message': 'I am the fourth view.'},
context_instance=RequestContext(request, processors=[custom_proc]))

同时,Django因此提供对 全局 context处理器的支持。Django提供了几个简单的context处理器,我们只需要在settings.py文件中配置:

TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
)

关于这几个处理器所返回的参数,可以详见Django book

回到我所遇到的问题,由于我的视图函数中的,有的使用了RequestContext 有的使用了locals(),返回的参数各不相同,导致视图函数无法得到realid值,也许表达不够清晰。举个例子,我的视图函数中使用了context_instance=RequestContext(request),但是我却令模板中的<a href={% url addarticle realid=request.user.id %}> 参数realid值为request.user.id,这就出现了错误,当你添加了locals()后就可以使用了,因为locals()返回request参数。

所以,为了方便,我把所有的视图函数加载模板的部分都改成了这个形式:

return render_to_response("**.html",locals(),context_instance=RequestContext(request))

 
 
分类: Django

Django模板引擎的研究的更多相关文章

  1. 关于Django模板引擎的研究

    原创博文,转载请注明出处. 以前曾遇到过错误Reverse for ‘*’ with arguments '()' and keyword arguments' not found.1其原因是没有给视 ...

  2. Django模板引擎

    Django作为Web框架,需要一种很便利的方法动态地生成 HTML 网页,因此有了模板这个概念.模板包含所需 HTML 的部分代码以及一些特殊语法,特殊语法用于描述如何将视图传递的数据动态插入HTM ...

  3. Express:模板引擎深入研究

    深入源码 首先,看下express模板默认配置. view:模板引擎模块,对应 require('./view'),结合 res.render(name) 更好了解些.下面会看下 view 模块. v ...

  4. django模板引擎自定义变量

    定义临时变量: {% with i=1 %} {{i}} {% endwith %} 定义对临时变量操作的tag 在templatetags中创建set_val.py 内容是 from django ...

  5. django模板语法之include

    假如我们有以下模板index.html,代码为: <!DOCTYPE html> <html lang="en"> <head> <met ...

  6. Django 2.0 学习(13):Django模板继承和静态文件

    Django模板继承和静态文件 模板继承(extend) Django模板引擎中最强大也是最复杂的部分就是模板继承了,模板继承可以让我们创建一个基本的"骨架"模板,它可以包含网页中 ...

  7. Django模板简介

    在settings.py中有个TEMPLATES的设置,其中BACKEND用来配置Django模板引擎, DIRS 定义了一个目录列表,模板引擎按列表顺序搜索这些目录以查找模板源文件 一般我们都会把模 ...

  8. djando模板----第一django模板应用

    Django模板 我们已经知道,模板函数的函数的返回值就是返回给客户端的数据,但如果返回数据很复杂,如果一个非常大的html页面,直接将页面代码固化在python脚本文件中是不合适的,当然 也可以将h ...

  9. Django模板自定义标签和过滤器,模板继承(extend),Django的模型层

    上回精彩回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

随机推荐

  1. (二)spring MVC配置

    使用Maven添加依赖的jar包 <!-- 自动扫描的包名 -->                                                 <mvc:reso ...

  2. MVC中实现多按钮提交(转)

    有时候会遇到这种情况:在一个表单上需要多个按钮来完成不同的功能,比如一个简单的审批功能. 如果是用webform那不需要讨论,但asp.net mvc中一个表单只能提交到一个Action处理,相对比较 ...

  3. Web字体@font-face对于中文字体的使用

    今天算是刚开始玩博客园..感觉很新鲜在首页 上看到了一个博客http://www.cnblogs.com/liuminghai/p/4238256.html是关于web文字的,挺不错 但是B/S的前端 ...

  4. Codeforces Round #243 (Div. 1)-A,B,C-D

    此CF真是可笑.. . 由于早晨7初始点,因此,要做好CF时间已经17没有休息一小时,加上中午5小时耐力赛. 心里很清楚.是第一个问题的时候,几乎被解读为寻求最大的领域和.然后找到一个水体,快速A降. ...

  5. CSS hack 如何区分所有IE浏览器和非IE浏览器

    网上方法很多,例如,测试后得出以下结论,多余的话不说了,直入主题: 1.所有的推理IE浏览器 正解:此写法仅仅被lE浏览器识别,非IE浏览器不识别. <!--[if IE]> <st ...

  6. 编写一个程序,将a.txt文件中的单词与b.txt文件中的单词交替合并到c.txt文件中,a.txt文件中的单词用回车符分隔,b.txt文件中用回车或空格进行分隔

    package sundemo2; import java.io.File; import java.io.FileReader; import java.io.FileWriter; public ...

  7. div中显示某个网页

    原文:div中显示某个网页 1.<iframe>方法 2.ajax方法 ajax+流实现无框架限制块刷新: 主框架index页面: js: $(function(){ $("#d ...

  8. JavaWeb显示器

    本文研究的总结.欢迎转载,但请注明出处:http://blog.csdn.net/pistolove/article/details/44310967 A:监听器的定义      专门用于其它对象身上 ...

  9. jquery+css3打造一款ajax分页插件

    原文:[原创]jquery+css3打造一款ajax分页插件 最近公司的项目将好多分页改成了ajax的前台分页以前写的分页插件就不好用了,遂重写一个 支持IE6+,但没有动画效果如果没有硬需求,个人认 ...

  10. C++程序中应增加STL、运算和字符串的头文件

    #include <complex> //模板类complex的标准头文件 #include <valarray> //模板类valarray的标准头文件 #include & ...