1. 模板的组成
- HTML代码+逻辑控制代码
2. 逻辑控制代码的组成
2.1 变量格式: {{var_name}}
# 示例: Template 和 Context 对象
# Terminal
python manage.py shell # 进入该django项目的环境
from django.template import Context, Template
t = Template('My name is {{ name }}')
c = Context({'name':'xiaohu'})
t.render(c)
# 同一模板,多个上下文,一旦有了模板对象,就可以通过它渲染多个context,无论何时我们都可以像这样
# 使用同一模板源渲染多个 context,只进行一次模板创建,然后多次调用 render()方法渲染会更为高效:
# 低效:
from name in ('小虎','小猪','旺仔'):
t = Template('Hello, {{ name }}')
print t.render(Context({'name': name}))
# 推荐
t = Template('Hello, {{ name }}')
from name in ('小虎','小猪','旺仔'):
print t.render(Context({'name': name}))
2.2 万能的句点号
- 到目前为止,我们通过context传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据
结构,例如list
,dictionary
和自定义的对象。 - 在Django模板中遍历复杂数据结构的关键是句点字符(
.
)
# 以下均在 iTerm 中操作
# 示例一:句点可用于访问列表索引
from django.template import Template, Context
t = Template('I have ate {{ items.2 }}')
c = Context({'items': ['apples', 'bananas', 'carrots']})
t.render(c) # 输出: I have ate carrots
# 示例二:通过字典键访问字典的值,可以使用句点
from django.template import Template, Context
person = {'name':'xiaohu', 'age':'22'}
t = Template('{{ person.name }} is {{ person.age }} years old.')
c = Context({'person':person})
t.render(c) # 输出: xiaohu is 22 years old.
# 示例三: 通过句点访问对象的属性.例如,Python中 datetime.date 对象有 year, month, day 几个属性
from django.template import Template, Context
import datetime
d = datetime.date(1998, 2, 18)
t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
c = Context({'date': d})
t.render(c) # 输出: The month is 2 and the year is 1998.
# 示例四: 通过句点访问自定义对象的属性
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('Jhon', 'Smith')})
t.render(c)
# 示例五: 通过句点访问对象的方法
from django.template import Template, Context
t = Template('{{ var }} --- {{ var.upper }} -- {{ var.isdigit }}')
t.render(Context({'var':'hello'}))
# 输出: hello -- HELLO -- False
# 注意:
# 这里调用方法时,并没有使用圆括号,而且也无法给该方法传递参数;只能调用不需要参数的方法;
2.3 变量的过滤器(filter)
# 语法格式:
{{obj|filter:param}}
# param 的值:
# add: 给变量加上相应的值;
# addslashes: 给变量中的引号前加上斜线;
# capfirst: 首字母大写;
# cut: 从字符串中移除指定的字符;
# date: 格式化日期字符串;
# default: 如果值是False, 就替换成设置的默认值,否则就用本来的值;
# default_if_none: 如果值是None,就替换成设置的默认值,否则就用本来的值;
# 示例:
# value1='aBcDe'
{{ value|upper }}<br/>
# value2=5
{{ value2|add:3 }}<br/>
# value3='he llo wo r ld'
{{ value3|cut:' '}}<br/>
# import datetime
# value4=datetime.datetime.now()
{{ value4|date:'Y-m-d'}}<br/>
# value5=[]
{{ value5|default:'空的'}}<br/>
#value6='<a href="#">跳转</a>'
{{ value6 }}
{% autoescape off %}
{{ value6 }}
{% endautoescape %}
{{ value6|safe }}<br/>
{{ value6|striptags }}
# value7='1234'
{{ value7|filesizeformat }}<br/>
{{ value7|first }}<br/>
{{ value7|length }}<br/>
{{ value7|slice:':-1'}}<br/>
2.4 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)
{% tags %}
# 示例一: {% if %}
{% if num >= 100%}
{% if num > 200 %}
<p>num大于200</p>
{% else %}
<p>num大于100小于200</p>
{% endif %}
{% elif num < 100 %}
<p>num 小于100</p>
{% else %}
<p>num 等于100</p>
{% endif %}
# 示例二:{% for %}
<ul>
{% for obj in list %}
<li>{{ obj.name }}</li>
{% endfor %}
</ul>
# 在标签里添加reversed,来反序循环列表
{% for obj in list reversed %}
....
{% endfor %}
# 系统不支持中断循环,也不支持continue语句, {% for %}标签内置了一个forloop模板变量,
# 这个变量含有一些属性可以提供一些关于循环的信息;
# forloop.counter 表示循环的次数,它从1开始计数,第一次循环设为1:
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
# forloop.counter0 类似于forloop.counter, 但它是从0开始计数,第一次循环设为0
# forloop.first 当第一次循环时,值为True:
{% for object in objects %}
{% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
{{ object }}
</li>
{% endfor %}
# 示例三: {% csrf_token %}
# 用于生成 csrf_token 标签,用于防止跨站攻击验证;如果在view的index里用的是 render_to_response 方法,
# 不会生效;
# {% csrf_token %} 其实,这里生成一个 input 标签,和其他表单标签一起提交给后台;
<form action="{% url 'book' %}">
<input type="text" name="username">
<input type="password" name="pwd">
<input type="submit" value="提交">
{% csrf_token %}
</form>
# 示例四: {% with %} 用更简单的变量名替换复杂的变量名
{% with total=fhdhdfkldflkdf %}{{ total }}{% endwith %}
# 示例五: {% verbatin %} 原样输出
{% verebatim %}
{{ hello }}
{% endverbatim %}
2.5 自定义 simple_tag
# 示例: 自定义filter 和 simple_tag
# Step1: 创建 mysite/templatetags 模块(名称固定)
# Step2: 在该文件夹下,创建任意 .py 文件,例如,my_tags.py
# Step3: 编写自定义代码 mysite/templatetags/my_tags.py
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # register 的名称是固定的,不可改变
@register.filter
def fitler_multi(v1, v2):
return v1 * v2
@register.simple_tag
def simple_tag_multi(v1, v2):
return v1 * v2
@register.simple_tag
def my_input(id, arg):
result = "<input type='text' id='%s' class='%s' />" % (id, arg,)
return mark_safe(result)
# Step4: 在html文件中,导入自定义的 my_tags.py
{% load my_tags %}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
{{ num|filter_multi:2 }}
{% simple_tag_multi 2 5 %}
</body>
</html>
# Step5: 在 settings 中的 INSTALLED_APPS 配置当前项目 mysite
# 注意:
# filter 可以用在 if 等语句后, simple_tag 不可以
{% if num|filter_multi:30 > 100 %}
{{ num|filter_multi:30 }}
{% endif %}
2.6 extend 模板继承
- 模板继承:就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载;
# 示例:
# Step1: 定义基础模板
# templates/base.html
<!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>
# 子模板的作用就是重载,添加或保留那些块的内容
# current_datetime.html
{% extends "base.html" %}
{% block title %}The current time{% endblock%}
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
# hours_head.html
{% extends "base.html"%}
{% block title %}Future time{% endblock %}
{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock%}
参考资料: