在day4中,你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python 代码之中。

   html = "<html><body>It is now %s.</body></html>" % now

尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意。 让我们来看一下为什么:

  • 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。

  • Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。

  • 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式 。

模板介绍

让我们从一个简单的例子模板开始。 该模板描述了一个向某个与公司签单人员致谢 HTML 页面。 可将其视为一个格式信函:

<html>
<head><title>Ordering notice</title></head> <body> <h1>Ordering notice</h1> <p>Dear {{ person_name }},</p> <p>Thanks for placing an order from {{ company }}. It's scheduled to
ship 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>
{% else %}
<p>You didn't order a warranty, so you're on your own when
the products inevitably stop working.</p>
{% endif %} <p>Sincerely,<br />{{ company }}</p> </body>
</html>

用两个大括号括起来的文字(例如 {{ person_name }} )称为 变量(variable) 。

被大括号和百分号包围的文本(例如 {% if ordered_warranty %} )是 模板标签(template tag) 。

最后,这个模板的第二段中有一个关于filter过滤器的例子,它是一种最便捷的转换变量输出格式的方式。 如这个例子中的{{ship_date|date:”F j, Y” }},我们将变量ship_date传递给date过滤器,同时指定参数”F j,Y”。date过滤器根据参数进行格式输出。

使用模板系统

  1. 可以用原始的模板代码字符串创建一个 Template 对象, Django同样支持用指定模板文件路径的方式来创建 Template 对象;

  1. 调用模板对象的render方法,并且传入一套变量context。它将返回一个基于模板的展现字符串,模板中的变量和标签会被context值替换。

(django) e:\Django\mysite>python  manage.py shell
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Inte
l)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django import template
>>> t = template.Template('My name is {{ name }}.')
>>> c = template.Context({'name': 'Adrian'})
>>> print(t.render(c))
My name is Adrian.
>>> c = template.Context({'name': 'Fred'})
>>> print(t.render(c))
My name is Fred.
>>>
Template你可以当做一个模板对象。模板也可以用多行注释符写。

Context就是类似于字典的对象。  变量名必须由英文字符开始 (A-Z或a-z)并可以包含数字字符、下划线和小数点。 

记住要用 python manage.py shell这个命令进入python中,而不能直接在命令行输入python进入到终端,否则会出错。

manage.py shell命令有一个重要的不同: 在启动解释器之前,它告诉Django使用哪个设置文件。 Django框架的大部分子系统,包括模板系统,都依赖于配置文件;如果Django不知道使用哪个配置文件,这些系统将不能工作。


深度变量的查找

在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

最好是用几个例子来说明一下。 比如,假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:

>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': ''}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
u'Sally is 43 years old.'

同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有 year 、 month 和 day几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
u'The month is 5 and the year is 1993.'

这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适用于任意的对象。

>>> 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)
u'Hello, John Smith.'

点语法也可以用来引用对象的* 方法*。 例如,每个 Python 字符串都有 upper() 和 isdigit() 方法,你在模板中可以使用同样的句点语法来调用它们:

>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
u'hello -- HELLO -- False'
>>> t.render(Context({'var': ''}))
u'123 -- 123 -- True'

点语法还能用于访问列表索引

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
u'Item 2 is carrots.'

{% if %}

  • {% if %} 标签接受 and , or 或者 not 关键字来对多个变量做判断。
  • {% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的
  • {% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的
  • 并没有 {% elif %} 标签, 请使用嵌套的`` {% if %}`` 标签来达成同样的效果
  • 一定要用 {% endif %} 关闭每一个 {% if %} 标签。

{% for %}

  • {% for %} 允许我们在一个序列上迭代:{% for athlete in athlete_list %}
  • 给标签增加一个 reversed 使得该列表被反向迭代:{% for athlete in athlete_list reversed %}
  • 可以嵌套使用 {% for %} 标签
  • 结束要用{% endfor %}

在执行循环之前先检测列表的大小是一个通常的做法,当列表为空时输出一些特别的提示。`` for`` 标签支持一个可选的`` {% empty %}`` 分句,通过它我们可以定义当列表为空时的输出内容 下面的例子与之前那个等价:

{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>
{% empty %}
<p>There are no athletes. Only computer programmers.</p>
{% endfor %} 等价于
{% if athlete_list %}
{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>
{% endfor %}
{% else %}
<p>There are no athletes. Only computer programmers.</p>
{% endif %}
  • 每个`` {% for %}``循环里有一个称为`` forloop`` 的模板变量。这个变量有一些提示循环进度信息的属性。
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
  • forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为```` 在下面的情形中这个变量是很有用的:
{% for object in objects %}
{% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
{{ object }}
</li>
{% endfor %}

{% ifequal %}

  • {% ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。

下面的例子比较两个模板变量 user 和 currentuser :

{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}
  • 和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签
  • 只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数

注释

{# This is a comment #}
用这种语法的注释不能跨越多行
注释的内容不会在模板渲染时输出。 如果要实现多行注释,可以使用`` {% comment %}`` 模板标签,就像这样:
{% comment %}
This is a
multi-line comment.
{% endcomment %}

过滤器

就象本章前面提到的一样,模板过滤器是在变量被显示前修改它的值的一个简单方法。 过滤器使用管道字符,如下所示:

{{ name|lower }}
显示的内容是变量 {{ name }} 被过滤器 lower 处理后的结果,它功能是转换文本为小写。 过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入,如此下去。 下面的例子实现查找列表的第一个元素并将其转化为大写。 {{ my_list|first|upper }}
有些过滤器有参数。 过滤器的参数跟随冒号之后并且总是以双引号包含。 例如: {{ bio|truncatewords:"" }}
这个将显示变量 bio 的前30个词。

  addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 这在处理包含JavaScript的文本时是非常有用的。

  date : 按指定的格式字符串参数格式化 date 或者 datetime 对象

 

模板加载

要使用此模板加载API,首先你必须将模板的保存位置告诉框架。

先在mysite下创建一个templates文件夹,用于存放模板。

 
settings.py:
'DIRS': [os.path.join(BASE_DIR, 'templates')],
如果想要更灵活一点并减少一些负面干扰,可利用 Django 配置文件就是 Python 代码这一点来动态构建 TEMPLATE_DIRS 的内容,如: 例如:
import os
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),

完成 TEMPLATE_DIRS 设置后,下一步就是修改视图代码,让它使用 Django 模板加载功能而不是对模板路径硬编码。 返回 current_datetime 视图,进行如下修改:

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)

这里的django2.2中使用出现编码错误,暂时找不到原因。

render_to_response()

我们已经告诉你如何载入一个模板文件,然后用 Context渲染它,最后返回这个处理好的HttpResponse对象给用户。 我们已经优化了方案,使用 get_template() 方法代替繁杂的用代码来处理模板及其路径的工作。 但这仍然需要一定量的时间来敲出这些简化的代码。 这是一个普遍存在的重复苦力劳动。Django为此提供了一个捷径,让你一次性地载入某个模板文件,渲染它,然后将此作为 HttpResponse返回。

下面就是使用 render_to_response() 重新编写过的 current_datetime 范例。

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() 使用一个空字典。

render()

render()与render_to_response()类似,查看源码:

def render_to_response(template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
warnings.warn(
'render_to_response() is deprecated in favor of render(). It has the '
'same signature except that it also requires a request.',
RemovedInDjango30Warning, stacklevel=2,
)
content = loader.render_to_string(template_name, context, using=using)
return HttpResponse(content, content_type, status) def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)

发现render()函数多了一个request参数,如果你要传入request参数就要用render()函数

使用如下:


from django.http import HttpResponse,Http404
import datetime

from django.shortcuts import render

def current_datetime(request):
now = datetime.datetime.now()
return render(request,'current_datetime.html', {'current_date': now})

locals() 技巧

def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})
很多时候,就像在这个范例中那样,你发现自己一直在计算某个变量,保存结果到变量中(比如前面代码中的 now ),然后将这些变量发送给模板。 尤其喜欢偷懒的程序员应该注意到了,不断地为临时变量和临时模板命名有那么一点点多余。 不仅多余,而且需要额外的输入。 如果你是个喜欢偷懒的程序员并想让代码看起来更加简明,可以利用 Python 的内建函数 locals() 。它返回的字典对所有局部变量的名称与值进行映射。 因此,前面的视图可以重写成下面这个样子: def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())
在此,我们没有像之前那样手工指定 context 字典,而是传入了 locals() 的值,它囊括了函数执行到该时间点时所定义的一切变量。 因此,我们将 now 变量重命名为 current_date ,因为那才是模板所预期的变量名称。 在本例中, locals() 并没有带来多 大 的改进,但是如果有多个模板变量要界定而你又想偷懒,这种技术可以减少一些键盘输入。

使用 locals() 时要注意是它将包括 所有 的局部变量,它们可能比你想让模板访问的要多。 在前例中, locals() 还包含了 request 。对此如何取舍取决你的应用程序。

include 模板标签

在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。

下面这两个例子都包含了 nav.html 模板。这两个例子是等价的,它们证明单/双引号都是允许的。

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

下面的例子包含了 includes/nav.html 模板的内容:

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

下面的例子包含了以变量 template_name 的值为名称的模板内容:

{% include template_name %}
例:
#current_datetime.html
<html>
<body>
It is now {{ current_date }}.
{% include 'nav.html' %}
</body>
</html> #nav.html
<html>
<body>
<p>这是导入的页面</p>
</body>
</html> #打开显示
It is now April 12, 2019, 9:46 p.m..
这是导入的页面
文章引用:http://docs.30c.org/djangobook2/chapter04/index.html

Django学习day6——模板的更多相关文章

  1. django学习-6.模板templates

    1.前言 首先,我们要知道html是一门静态语言,里面没法传一些动态参数,也就是一个写死的html页面. 那么,如果我们想实现在一个html页面里传入不同的参数对应的参数值,这就可以用django框架 ...

  2. django 学习-5 模板使用流程

    首先在模板下建一个index.html <!DOCTYPE html><html><head><meta charset="utf-8" ...

  3. django 学习-2 模板

    如何使用渲染模板的方法来显示内容. 1.创建一个项目dream django-admin.py   startproject   dream cd  dream    再创建一个应用 python m ...

  4. django学习笔记-模板层

    模板层 将Python嵌入到HTML中. 模板简介 将HTML硬解码到视图并不是那么完美原因如下: 对页面设计时也需要对python代码进行相应的修改,模板可以不就行python代码修改的情况下变更设 ...

  5. django学习--2 模板

    Django 模板 在上一章节中我们使用 django.http.HttpResponse() 来输出 "Hello World!".该方式将数据与视图混合在一起,不符合 Djan ...

  6. Django学习之模板

    一.常用语法 1.变量 2.Filters 3.自定义filter 4.Tags 5.csrf_token 6.注释 7.注意事项 二.母板 2.继承母板 3.块(block) 4.组件 5.静态文件 ...

  7. Django 学习 之 模板(html)与配置静态文件

     一.模板(html) 1.模板语法之变量:语法为 {{ }} 在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法:{{ var_name }} var_name 是一个变量名称,需要和 ...

  8. Django学习之模板层

    三板斧 render,HttpResponse,redirectrender返回一个HTML页面,并且还能够给该页面传数据render内部原理: from django.template import ...

  9. django 学习-3 模板变量

    1.vim learn/home.html <!DOCTYPE html><html><head>        <title>{{title}}< ...

随机推荐

  1. 设计时数据源:在PostgreSql 数据查询中使用参数过滤

    在上一篇文章中,我们学习了如何设计时连接PostgreSQL 数据库及环境搭建.本节我们来学习使用PostgreSql 数据源时,创建数据集时带参数过滤的查询语句写法. 在报表中包含两种参数,可参考博 ...

  2. jquery复习日记(1)

    jquery封装了JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作.事件处理.动画设计和Ajax交互. 核心关键字: 链式.多功能.高效灵活   1 ...

  3. ELK 学习笔记之 Logstash之codec配置

    Logstash之codec: Logstash处理流程: input=>decode=>filter=>encode=>output 分类: Plain编码: input{ ...

  4. asp.net 开源工作流-ccflow关于 “ 是否自动计算未来的处理人”的功能变更

    关键字:流程未来节点处理人  工作流快速开发平台  工作流流设计  业务流程管理   asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向.对于另 ...

  5. Cheapest Palindrome POJ - 3280

    Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate ...

  6. 【DP合集】背包 bound

    N 种物品,第 i 种物品有 s i 个,单个重量为 w i ,单个价值为 v i .现有一个限重为 W 的背包,求能容 纳的物品的最大总价值. Input 输入第一行二个整数 N , W ( N ≤ ...

  7. asp.net 重写OnException返回json或跳转新页面

    protected override void OnException(ExceptionContext filterContext) { // 此处进行异常记录,可以记录到数据库或文本,也可以使用其 ...

  8. from..import 语句

    from..import 语句 如果你希望直接将 argv 变量导入你的程序(为了避免每次都要输入 sys.),那么你可以通过使用 from sys import argv 语句来实现这一点. 警告: ...

  9. 在web端使用html5访问远程桌面

    背景: 2019年12月5日,微软宣布放弃浏览器Edge,转而推出一款新的浏览器,而这款新浏览器将会采用谷歌的Chromium 内核... 好了,反正已经无力吐槽,微软烂尾的项目也不是一个两个了,之前 ...

  10. Vmware Ubuntu 开机蓝屏

    引用:http://tieba.baidu.com/p/4898482611 1. 这是vm的一个bug!!!打开你的虚拟系统目录,编辑虚拟机文件夹下面的.vmx 用记事本打开,加入代码. cpuid ...