Django学习day6——模板
在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过滤器根据参数进行格式输出。
使用模板系统
可以用原始的模板代码字符串创建一个 Template 对象, Django同样支持用指定模板文件路径的方式来创建 Template 对象;
调用模板对象的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——模板的更多相关文章
- django学习-6.模板templates
1.前言 首先,我们要知道html是一门静态语言,里面没法传一些动态参数,也就是一个写死的html页面. 那么,如果我们想实现在一个html页面里传入不同的参数对应的参数值,这就可以用django框架 ...
- django 学习-5 模板使用流程
首先在模板下建一个index.html <!DOCTYPE html><html><head><meta charset="utf-8" ...
- django 学习-2 模板
如何使用渲染模板的方法来显示内容. 1.创建一个项目dream django-admin.py startproject dream cd dream 再创建一个应用 python m ...
- django学习笔记-模板层
模板层 将Python嵌入到HTML中. 模板简介 将HTML硬解码到视图并不是那么完美原因如下: 对页面设计时也需要对python代码进行相应的修改,模板可以不就行python代码修改的情况下变更设 ...
- django学习--2 模板
Django 模板 在上一章节中我们使用 django.http.HttpResponse() 来输出 "Hello World!".该方式将数据与视图混合在一起,不符合 Djan ...
- Django学习之模板
一.常用语法 1.变量 2.Filters 3.自定义filter 4.Tags 5.csrf_token 6.注释 7.注意事项 二.母板 2.继承母板 3.块(block) 4.组件 5.静态文件 ...
- Django 学习 之 模板(html)与配置静态文件
一.模板(html) 1.模板语法之变量:语法为 {{ }} 在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法:{{ var_name }} var_name 是一个变量名称,需要和 ...
- Django学习之模板层
三板斧 render,HttpResponse,redirectrender返回一个HTML页面,并且还能够给该页面传数据render内部原理: from django.template import ...
- django 学习-3 模板变量
1.vim learn/home.html <!DOCTYPE html><html><head> <title>{{title}}< ...
随机推荐
- 设计时数据源:在PostgreSql 数据查询中使用参数过滤
在上一篇文章中,我们学习了如何设计时连接PostgreSQL 数据库及环境搭建.本节我们来学习使用PostgreSql 数据源时,创建数据集时带参数过滤的查询语句写法. 在报表中包含两种参数,可参考博 ...
- jquery复习日记(1)
jquery封装了JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作.事件处理.动画设计和Ajax交互. 核心关键字: 链式.多功能.高效灵活 1 ...
- ELK 学习笔记之 Logstash之codec配置
Logstash之codec: Logstash处理流程: input=>decode=>filter=>encode=>output 分类: Plain编码: input{ ...
- asp.net 开源工作流-ccflow关于 “ 是否自动计算未来的处理人”的功能变更
关键字:流程未来节点处理人 工作流快速开发平台 工作流流设计 业务流程管理 asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向.对于另 ...
- Cheapest Palindrome POJ - 3280
Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate ...
- 【DP合集】背包 bound
N 种物品,第 i 种物品有 s i 个,单个重量为 w i ,单个价值为 v i .现有一个限重为 W 的背包,求能容 纳的物品的最大总价值. Input 输入第一行二个整数 N , W ( N ≤ ...
- asp.net 重写OnException返回json或跳转新页面
protected override void OnException(ExceptionContext filterContext) { // 此处进行异常记录,可以记录到数据库或文本,也可以使用其 ...
- from..import 语句
from..import 语句 如果你希望直接将 argv 变量导入你的程序(为了避免每次都要输入 sys.),那么你可以通过使用 from sys import argv 语句来实现这一点. 警告: ...
- 在web端使用html5访问远程桌面
背景: 2019年12月5日,微软宣布放弃浏览器Edge,转而推出一款新的浏览器,而这款新浏览器将会采用谷歌的Chromium 内核... 好了,反正已经无力吐槽,微软烂尾的项目也不是一个两个了,之前 ...
- Vmware Ubuntu 开机蓝屏
引用:http://tieba.baidu.com/p/4898482611 1. 这是vm的一个bug!!!打开你的虚拟系统目录,编辑虚拟机文件夹下面的.vmx 用记事本打开,加入代码. cpuid ...