在上一章,我们页面显示的html代码是直接编写在python代码中,因为对页面的设计修改工作要比python频繁的多,所以最好将页面设计工作和python代码分离,所以我们引用模板来实现这个功能。
一、模板实例
下面是一个模板的实例:
<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>分析其中的一些元素:
(1)用大括号括起来的称作:变量,需要对它进行赋值
(2)用大括号和百分号括起来的是:模板标签,即通知模板系统完成某些工作的标签。上文中有两个模板标签:for和if分别实现循环和判断。
(3)第二段有个filter过滤器的使用:
{{ ship_date|date:"F j, Y" }
它是将变量ship_date传递给过滤器date,同时指定参数,过滤器按照参数输出。
二、使用模板
1、基本流程:
(1)用原始的模板代码创建一个Template对象
(2)创建一个Context对象,完成对模板对象中的变量赋值
(3)调用模板对象的render方法,将(2)步生成的context对象作为参数,填充模板,同时返回基于模板的展现字符串,这时其中的变量已经被替换。
实例:
>>> 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.2、创建模板对象
转到mysite所在的目录,输入
python manage.py shell
为什么我们运行pythonmanage.pyshell而不是python的。这两个命令都会启动交互解释器,但是manage.pyshell命令有一个重要的不同: 在启动解释器之前,它告诉Django使用哪个设置文件。 Django框架的大部分子系统,包括模板系统,都依赖于配置文件;如果Django不知道使用哪个配置文件,这些系统将不能工作。
>>> from django import template >>> t = template.Template('My name is {{ name }}.') >>> print t <django.template.base.Template object at 0x0220EBD0>每次创建一个template对象,打印出来的地址都不同。
3、模板渲染
即,对模板内的变量、标签赋值。
使用context来传递数据,一个context是一系列变量和他们的值的集合,然后用template的render方法传递context填充模板。
>>> from django import template >>> t = template.Template('My name is {{ name }}.') >>> c = template.Context('name': 'Jim') >>> t.render(c) u'My name is Jim.'
>>> from django.template import Template, Context >>> raw_template = """<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> ... ... {% 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>""" >>> t = Template(raw_template) >>> import datetime >>> c = Context({'person_name': 'John Smith', ... 'company': 'Outdoor Equipment', ... 'ship_date': datetime.date(2009, 4, 2), ... 'ordered_warranty': False}) >>> t.render(c) u"<p>Dear John Smith,</p>\n\n<p>Thanks for placing an order from Outdoor Equipment. It's scheduled to\nship on April 2, 2009.</p>\n\n\n<p>You didn't order a warranty, so you're on your own when\nthe products inevitably stop working.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment </p>"
输出的结果没有按照\n显示换行,这和python解释器有关,它会按照真实内容显示,如果想显示出换行,使用print t.render(c)
4、一个模板多个渲染一旦定义了一个模板,就可以渲染多个context
>>> from django.template import Template, Context >>> t = Template('My name is {{ name }}.') >>> print t.render(Context{'name': 'Jim'}) My name is Jim. >>> print t.render(Context{'name': 'Pat'}) My name is Pat.
>>> from django.template import Template, Context >>> t = Template('Hello, {{ name }}') >>> for name in ('John', 'Juile', 'pat'): ... print t.render(Context({'name': name})) ... Hello, John Hello, Juile Hello, pat
5、深度查找
通过使用点号(.)遍历模板中复杂的数据结构。
5.1访问字典值
>>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) u'Sally is 43 years old.'5.2访问对象属性
>>> 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.'5.3访问自定义类的属性
>>> 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.'5.4引用对象的方法
>>> 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': '123'})) u'123 -- 123 -- True'每个python字符串都有upper(),lower()和isdigit()方法,分别将字符串转换为大写、小写以及判断是否为数字。这里调用的方法后没有括号,所以只能调用没有参数的方法。
5.5访问列表索引
>>> 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.'注:不允许使用负数的列表索引
6、句点的查找规则
当模板系统在变量名中遇到句点时,按照以下顺序查找:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %}if标签检查变量tody_is_weekend ,如果该变量为真,则执行{% if %}和{% endif %}或者和{% else %}之间的内容。{% else %}是可选的。在python和django模板系统中,以下对象相当于布尔值False:
{% if athlete_list and coach_list or cheerleader_list %}同时系统不支持用圆括号来组合比较操作,可以使用嵌套的{% if %} 标签来代替。
{% if athlete_list %} {% if coach_list or cheerleader_list %} We have athletes, and either coaches or cheerleaders! {% endif %} {% endif %}可以多次使用同一个逻辑操作符,但是不能把不同的操作符组合起来。例如,以下是合法的:
{% if athlete_list or coach_list or parent_list or teacher_list %}注意:没有{% elif %}标签,要使用嵌套的{% if %}来达到这个效果,同时每个{% if %}必须用{% endif %}标签结束。
<ul> {% for athlete in athlete_list%} <li>{{ athlete.name }}</li> {% endfor %} </ul>还可以嵌套使用for循环。
{% if athlete_list %} {% for athlete in athlete_list %} <p>{{ athlete.name }}</p> <% endfor %> {% else %} <p> There are no athletes.</p> <% endif %>但是可以使用{% empty %}标签定义列表为空时的输出内容:
{% for athlete in athlete_list %} <p>{{ athlete.name }}</p> {% empty %} <p> There are no athletes.</p> <% endfor %>这个和上面的例子等价。
{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li> <% endif %> {{ object }} </li> {% endfor %}6)forloop.last:布尔值,在最后一次执行时被置为true
{% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}7)forloop.parentloop:是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。
{% ifequal variable 1 %} {% ifequal variable 1.23 %} {% ifequal variable 'foo' %} {% ifequal variable "foo" %} {% ifequal section 'sitenews' %} <h1>Site News</h1> {% else %} <h1>No News Here</h1> {% endifequal %}注:布尔、字典、列表类型不能用在{% ifequal %}中。
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(___file___), 'templates').replace('\\','/'), )os.path.dirname(__file__)会获取setting.py 所在的目录,然后这个目录与templates连接。我们可以使用render_to_response()方法进一步简化代码。注:file两侧是两个下划线。
<html> <body> It is now {{current_date}}. </body> </html>3)、编写views.py 文件
from django.shortcuts import render_to_response import datetime def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_date.html',{'current_date': now})4)、修改urls.py
from django.conf.urls.defaults import patterns, include, url from mysite.views import current_datetime urlpatterns = patterns('', ('^current_time/$', current_datetime), )2、使用locals()
def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})使用后:
def current_datetime(request): current_date = datetime.datetime.now() return render_to_response('current_datetime.html', locals())直接使用与模板中的变量相同的名字命名临时变量current_date,调用的时候使用locals,它囊括了函数执行到该时间点定义的所有变量。
t = get_template('dateapp/current_datetime.html')由于 render_to_response() 只是对 get_template() 的简单封装, 你可以对 render_to_response() 的第一个参数做相同处理:
return render_to_response('dateapp/current_datetime.html', {'current_date': now})4、include模板标签
{% include 'nav.html' %} {% include "nav.html" %}
{% include 'includes/nav.html' %}包含了以变量 template_name 的值为名称的模板内容:
{% include template_name %}六、模板继承
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html>2、修改模板使用该基础模板
{% extends "base.html" %} {% block title %}The current time{% endblock %} {% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}修改hours_ahead.html
{% extends "base.html" %} {% block title %}Future time{% endblock %} {% block content %} <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> {% endblock %}3、views.py
from django.shortcuts import render_to_response import datetime def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_date.html',{'current_date': now}) def hours_ahead(request, hours_offset): try: hours_offset = int(hours_offset) except ValueError: raise Http404() next_time= datetime.datetime.now() + datetime.timedelta(hours=hours_offset) return render_to_response('hours_ahead.html', locals())你可以根据需要使用任意多的继承次数。 使用继承的一种常见方式是下面的三层法: