最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过。Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧~

  本篇笔记(其实我的所有笔记都是),并不会过于详细的讲解。因此如果有大家看不明白的地方,欢迎在我正版博客下留言,有时间的时候我很愿意来这里与大家探讨问题。(当然,不能是简简单单就可以百度到的问题-.-)

  我所选用的教材是《The Django Book 2.0》,本节是第九章,模板高级进阶。


  本节书中内容仅是参考,更多是按照文档中内容来介绍。

  主要是因为书中版本过时,很多代码恰好是1.8中更新的内容,因此只得直接看文档了。


0. 目录

  1. RequestContext函数和context处理器

  2. html自动转义

  3. Django如何加载模板

    3.1 什么是Engine

    3.2 加载模板的语句

    3.3 模板加载器

1. RequestContext函数和context处理器

  首先,我们回顾模板的视图函数如何书写:

from django.shortcuts import render_to_response

def diary(request):
return render_to_response('diary.html', {'name': 'qiqi'})

  为了说明方便,我们同时给出另一种写法:

from django.http import HttpResponse
from django.template import loader, Context def diary(request):
t = loader.get_template('diary.html')
c = Context({'name': 'qiqi'})
return HttpResponse(t.render(c))

  或许还是有同学看不懂,那我就再给出第三种最笨的等价写法,大家大可略过直接往后看:

from django.http import HttpResponse
from django.template import Template, Context def diary(request):
tin = open('./templates/diary.html')
html = tin.read()
tin.close() inf = {'name': 'qiqi'} t = Template(html)
c = Context(inf)
return HttpResponse(t.render(c))

  在上述代码中,我们是用Context函数进行渲染的。

  而与django.template.Context函数差不多的,还有一个django.template.RequestContext函数,它默认在模板中加了一些变量,比如HttpRequest对象、当前登录用户的相关信息……

  来看下面这段代码:

from django.http import HttpResponse
from django.template import loader, Context def view_1(request):
# ...
t = loader.get_template('template1.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am view 1.'
})
return HttpResponse(t.render(c)) def view_2(request):
# ...
t = loader.get_template('template2.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the second view.'
})
return HttpResponse(t.render(c))

  其中app、user、ip_address这三个变量,可能需要在很多模板的渲染中重复写入,很麻烦。而利用RequestContext函数,我们便可以将之简化为这样:

from django.http import HttpResponse
from django.template import loader, RequestContext def custom_proc(request):
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
} def view_1(request):
# ...
t = loader.get_template('template1.html')
c = RequestContext(request, {'message': 'I am view 1.'}, [custom_proc])
return HttpResponse(t.render(c)) def view_2(request):
# ...
t = loader.get_template('template2.html')
c = RequestContext(request, {'message': 'I am the second view.'}, [custom_proc])
return HttpResponse(t.render(c))

  其中,我们写的函数custom_proc,便称为context处理器。用术语来说,我们利用RequestContext函数和context处理器,简化了使用模板的代码。

  而在此基础上使用render_to_response,我们还可以将之简化成:

from django.shortcuts import render_to_response
from django.template import RequestContext def custom_proc(request):
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, [custom_proc])) def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, [custom_proc]))

  此时,还是有一点美中不足的——渲染语句中,每次都需要手动为processors赋值。

  Django提供了对全局context处理器的支持——可以让你在全局变量中列出一些context处理器,Django在你每次调用RequestContext函数时都会自动加入这些处理器的。这个全局变量在TEMPLATES参数中可以找到,其默认值是:

# TEMPLATES参数中,'OPTIONS'字典中的,'context_processors'列表

[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
]

  这四个值不多说,可以去查书和手册。此时,我们可以进一步简化代码如下:

from django.shortcuts import render_to_response
from django.template import RequestContext def view_1(request):
# ...
return render_to_response('template1.html',
{'message': 'I am view 1.'},
context_instance=RequestContext(request)) def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request))

  至于context处理器,则应当写在单独的一份代码中,推荐命名为context_processors.py。

  只要把这份代码放在Python搜索路径中,Django就可以找到。推荐把它放在project或者app的目录下。

# context_processors.py

def custom_proc(request):
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}

  最后,修改全局变量即可:

[
'context_processors.custom_proc',
]

2. html自动转义

  从模板生成html时,总会有一个风险——变量包含了会影响html的字符。

  书中举了小例子,这里不加赘述,直接说解决方法:

    1. 确保每个不被信任的变量都用escape过滤器过滤一遍,把潜在的有害html字符转换为无害的。这是初几年Django的处理策略。

    2. 利用Django的html自动转义。下面介绍这种方法。

  只要你使用Django模板,那么变量标签中的以下五个字符都会被自动转义:

原字符 转义结果
< &lt;
> &gt;
' '
" &quot;
& &amp;

  当然,有时候你会自己手动用模板变量写一段html代码,那这时候你就需要关闭自动转义了,关闭方法如下:

    1. 变量级别,用safe过滤器: This will not be escaped: {{ data|safe }}

    2. 模板级别,用autoescape标签: {% autoescape off %} ... {% endautoescape %}

        这个标签有两种状态:off、on。

        这个标签是可以嵌套的,例如你可以在一个off的标签内嵌套on的标签。

        当你使用模板继承的时候,显而易见,这个标签依旧会持续生效的。

    3. 站点级别,这个书中只说有方法,却没写,暂时存疑。

  注意:

    1. 过滤多次和过滤一次效果完全一样。

    2. 模板中的字符串常量(例如过滤器中包含的常量)会逃过自动转义,而变量中的字符串则不会。

{{ data|default:"3 &lt; 2" }}
{{ data|default:"3 <" }} <-- Bad! Don't do this.

  存疑:

    1. escape过滤器是什么?根据文档中所写,好像是专指autoescape标签?

3. Django如何加载模板

  3.1 什么是Engine

    Engine,简单来说就是关于模板的一份设置,具体定义这里暂不介绍,大家可以先去文章开头所给的文档中查看,以后有时间会补上。

    平时加载模板,使用的就是Django中默认的一个Engine对象,其内容就是咱们在settings.py中那个TEMPLATES参数。因此,你用默认的方式加载模板,也就等同于你用Django中这个默认的Engine对象来加载模板。这个对象是: django.template.engines['django']

    而如果你想要实例化另一个Engine对象,则需要用这个定义: django.template.Engine()

  3.2 加载模板的语句

    Django加载模板的语句有三种:

      1. Engine.from_string(template_code)

        按照Engine对象的设置,编译所给代码生成模板,返回一个Template对象。

# 方法一,使用默认的Engine

from django.template import engines
template = engines['django'].from_string(template_code) # 方法二,使用一个空的Engine(没有context_processors之类的东西) from django.template import Engine
template = Engine().from_string(template_code)

      2. Engine.get_template(template_name)

        按照Engine对象的设置,根据所给名称找到模板,在内部进行编译,最后返回一个Template对象。

        如果模板不存在,则返回一个TemplateDoesNotExist的异常。

      3. Engine.select_template(self, template_name_list)

        按照Engine对象的设置,根据所给列表中的名称,顺次寻找模板,把找到的第一个同样处理,返回一个Template对象。

        如果全都不存在,则返回一个TemplateDoesNoeExist的异常。

  3.3 模板加载器

    我们一直说在加载模板,但是TEMPLATES参数中却并没有加载器的设置,此时我们所用的一直是Django中默认的加载器。

    下面,我们就一一介绍Django中的模板加载器:

      1. django.template.loaders.filesystem.Loader(默认)

        从文件系统中加载模板。

        路径:TEMPLATE参数中'DIRS'列表。

      2. django.template.loaders.app_directories.Loader

        从文件系统中加载模板。

        路径:各app,即INSTALLED_APPS参数每个app目录下的templates文件夹。

        开启方式:将TEMPLATES参数中'APP_DIRS'设置为True。

      3. django.template.loaders.eggs.Loader

        从Python egg中加载模板。

        路径:各app。

        开启方式:写出类似代码(未经测试,仅供参考)——

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'OPTIONS': {
'loaders': [
('django.template.loaders.eggs.Loader'),
],
},
}]

      4. django.template.loaders.cached.Loader

        加载模板时,第一次调用各加载器加载模板并存入缓存,以后则从缓存中直接加载模板。

        路径:取决于调用的各加载器。

        注意:实际加载的各模板应该保证其结点(Node)是进程安全(thread-safe)的,详见文档。

        开启方式:写出类似代码(源自文档)——

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'OPTIONS': {
'loaders': [
('django.template.loaders.cached.Loader', [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
]),
],
},
}]

      5. django.template.loaders.locmem.Loader

        从Python字典中加载模板,常用于测试。

        存疑:实际效果未测试过,不是很能理解。

        开启方式:写出类似代码(源自文档)——

TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'loaders': [
('django.template.loaders.locmem.Loader', {
'index.html': 'content here',
}),
],
},
}]

  实际上,书和文档中还提到了如何写自己的模板、模板中用于debug的两个类、如何写独立模型下的模板……

  但由于暂时还用不到,所以先不写了,等以后用到再补充。


  至此,“模板高级进阶”内容完结,下一篇是——“模型高级进阶”。

 

Django笔记 —— 模板高级进阶的更多相关文章

  1. Django笔记 —— 模型高级进阶

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  2. Django笔记 —— 模板

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  3. Django笔记&教程 5-2 进阶查询——Queryset

    Django 自学笔记兼学习教程第5章第2节--进阶查询--Queryset 点击查看教程总目录 Queryset相关内容其实蛮多的,本文只介绍一些常用的,详细的推荐查询官方文档:queryset-a ...

  4. django1.8读书笔记模版高级进阶

    一.概述 想要定制或者扩展模版引擎,模版系统工作原理,自动转移特征 名词解析:模板 渲染 就是是通过从context获取值来替换模板中变量并执行所有的模板标签. 二.Context处理器 如果在模版中 ...

  5. django1.8读书笔记模型高级进阶

    一.访问外键和多对多值 例如:模型类定义如下 from django.db import models class Publisher(models.Model): name = models.Cha ...

  6. Django之models高级进阶技术详解

    目录 一.常用字段 1.AutoField 2.IntegerField 3.CharField 4.自定义及使用char 5.DateField 6.DateTimeField 二.字段合集 三.字 ...

  7. Django笔记 —— 高级视图和URL配置

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  8. Django笔记 —— 基础部分总结

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  9. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

随机推荐

  1. MariaDB修改端口号

    修改端口号 打开my.ini文件

  2. @WebListener 注解方式实现监听(eclipse和idea)

    eclipse进行演示: 1.创建 Dynamic Web Project ,Dynamic Web module version选择3.0 2.在自动生成 的web.xml配置,增加 metadat ...

  3. 【luogu P2455 [SDOI2006]线性方程组】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2455 无解:最后一列对应元素不为0,前面全是0. 无穷解:一行全是0. 嗯...在消元过程中不要直接拿矩阵元 ...

  4. js 防抖 节流 JavaScript

    实际工作中,通过监听某些事件,如scroll事件检测滚动位置,根据滚动位置显示返回顶部按钮:如resize事件,对某些自适应页面调整DOM的渲染:如keyup事件,监听文字输入并调用接口进行模糊匹配等 ...

  5. js操作json方法总结

    相对于前端的老铁来说JSon并不陌生,JSON JavaScript Object Notation 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是一种理想的数据交换格式. json可以 ...

  6. 自己平时收集的css、html笔记(适合初级前端攻城狮)

    实习了一年时间,陆陆续续记录下来一堆笔记,不过也丢失了一些... 以后会持续更新.扩展,现在把碰到的知识点归纳于此,方便翻阅 一.html部分 1.取消iPhone自动识别数字为拨打号码 <me ...

  7. oracle中lock和latch的用途

    本文向各位阐述Oracle的Latch机制,Latch,用金山词霸翻译是门插栓,闭锁,专业术语叫锁存器,我开始接触时就不大明白为什么不写Lock,不都是锁吗?只是翻译不同而以?研究过后才知道两者有很大 ...

  8. rest_framework--RESTful规范

    #####RESTful规范##### 一.什么是restful restful其实就是一种软件架构风格,跟技术毫无关系.是一种面向资源编程的方法. 说起面向资源编程,我想起了之前了解到的面向过程编程 ...

  9. 【杂题总汇】AGC027 C - ABland Yard

    ◆AGC027◆C - ABland Yard 终于知道为什么比赛的时候这么多人做C题了…… +传送门+(这是beta版的) ◇ 题目(自己翻译的,不要在意细节……) P.S. (@ 2018-9-2 ...

  10. git设置.gitignore文件

    .gitignore用来忽略某些git仓库中不需要上传到远程仓库的文件,例如target目录.下面说一下步骤. 1.在项目根目录中通过右键Git Bash,打开控制命令台,新建一个.gitignore ...