目录
- 模板引擎DTL(django template language)
- 模板系统
- 使用模板系统
- 字典和上下文
- 基本的模板标签和过滤器
- 标签
- 过滤器
- 模板加载机制
- render()
- include模板标签
- 模板继承
模板引擎DTL(django template language)
模板系统
- 两对花括号包围的文本( { { 变量 }} )是变量,意思是“把指定变量的值插入这里”.
- 一对花括号和百分号包围的文本(如 {% 模板标签 %} )是模板标签
- 过滤器,这是调整变量格式:{ { 变量|过滤器:"参数" }}
- 内置模板标签和过滤器
使用模板系统
+ 编写模板字符串,创建 Template 对象,创建 Context 对象,然后调用 render() 方法。
+ 代码示例:
```
>>> from django import template
>>> t = template.Template('My name is {
{ name }}.') # 创建模板对象
>>> c = template.Context({'name': 'Nige'}) # 上下文(模板变量和相应的值)
>>> print (t.render(c)) # 渲染模板
My name is Nige.
```
+ 运行 python manage.py shell 启动交互式解释器,能在启动解释器之前,告诉Django 使用哪个设置文件,否则会抛异常
字典和上下文
多个上下文,同一个模板
>>> t = Template('Hello, { { name }}') >>> print (t.render(Context({'name': 'John'}))) Hello, John >>> print (t.render(Context({'name': 'Julie'}))) Hello, Julie
- 点号可以访问字典的键、属性、方法或对象的索引,板系统遇到变量名中的点号时会按照下述顺序尝试查找如foo.bar,foo.2
- 字典查找(如 foo["bar"] )
- 属性查找(如 foo.bar )
- 方法调用(如 foo.bar() )
- 列表索引查找(如 foo[2] )
- 模板系统在变量处插入引擎的 string_if_invalid 配置选项,(默认为一个空字符串):
- 方法设定了 alters_data=True ,那么渲染模板时不会执行方法
- 方法查找的过程中,如果方法抛出异常,异常有 silent_variable_failure 属性,而且值为 True
- 如果变量不存在
基本的模板标签和过滤器
标签
- if/else标签
- {% if ... %} 和 {% endif %}配对
- {% else %},{% elif %}
- {% if %} 支持使用 and 、 or 或 not, 优先级not,and,or,不能有括号
- for标签
- {% for ... in ...%}和{% forend %}配对
- {% for ... in ... reversed %}反向迭代
- {% empty %}子句,可迭代对象为空,则执行其后语句
- {% for %} 循环内部,可以访问一个名为 forloop 的模板变量,其属性:
- forloop.counter 的值是一个整数,表示循环的次数。这个属性的值从 1 开始
- forloop.counter0 与 forloop.counter 类似,不过是从零开始的
- forloop.revcounter 的值是一个整数,表示循环中剩余的元素数量
- forloop.revcounter0 与 forloop.revcounter 类似,不过索引是基于零的
- forloop.first 是个布尔值,第一次循环时为 True
- forloop.last 是个布尔值,最后一次循环时为 True
- 在嵌套的循环中, forloop.parentloop 引用父级循环的 forloop 对象
- ifequal/ifnotequal标签
- {% ifequal ... ...%} 标签比较两个值,如果相等,显示 {% ifequal %} 和 {% endifequal %} 之间的内容
- {% ifequal %} 标签支持可选的 {% else %} 子句
- {% ifequal %} 的参数只能是模板变量、字符串、整数和小数
- {% ifnotequal %} 测试两个参数是否不相等
- 注释
- 注释使用 {# #} 标明
- 多行注释{% comment %} ,{% endcomment %}
过滤器
+ {
{ name|lower }}: lower 过滤器调整 {
{ name }} 变量的值——把文本转换成小写
+ 过滤器可以串接:{
{ my_list|first|upper }},获取列表中的第一个元素,然后将其转换成大写
+ 有些过滤器可以接受参数:{
{ bio|truncatewords:"30" }},显示 bio 变量的前 30 个词
+ addslashes :在反斜线、单引号和双引号前面添加一个反斜线:{ value|addslashes }}
+ date :根据参数中的格式字符串格式化 date 或 datetime 对象:{
{ pub_date|date:"F j, Y"}},
+ length :返回值的长度。对列表来说,返回元素的数量。对字符串来说,返回字符的数量。如果变量未定义,返回 0 。
模板加载机制
- settings.py 文件中, TEMPLATES 设置。它的值是一个列表,分别针对各个模板引擎,模板引擎是字典,有以下设置:
- BACKEND 的值是Python 路径,指向实现 Django 模板后端 API 的模板引擎类。内置的后端有 djan-go.template.backends.django.DjangoTemplates 和 django.template.backends.jinja2.Jinja2 。
- DIRS 定义一个目录列表,模板引擎按顺序在里面查找模板源文件
- APP_DIRS 设定是否在安装的应用中查找模板。按约定, APPS_DIRS 设为 True 时, DjangoTemplates 会在INSTALLED_APPS 中的各个应用里查找名为“templates”的子目录
- OPTIONS 是一些针对后端的设置
- 在项目根目录中放一些主模板(例如在 mysite/templates 目录中):
'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 视图函数中使用模板加载机制
from django.template.loader import get_template
t = get_template('current_datetime.html') # 传入模块名称,返回模板对象
html = t.render(Context({'current_date': now})) # 出现类型错误,需要字典dir对象而不是Context对象,去掉Context直接{'current_date': now}或使用Context().update({'current_date': now)
render()
- django.shortcuts 模块中 render()
- 加载模板、创建上下文、渲染模板和创建 HttpResponse 对象全由 render() 调用代替, render() 的返回值是一个 HttpResponse 对象
- 例子:
from django.shortcuts import render
import datetime
def current_datetime(request):
now = datetime.datetime.now()
return render(request, 'current_datetime.html', {'current_date': now})
render() 的第一个参数是请求对象,第二个参数是模板名称,第三个单数可选,是一个字段,用于创建传给模板的上下文。如果不指定第三个参数, render() 使用一个空字典。
- 把模板存储在模板目录的子目录里,只需在模板名称前面加上子目录的名称和一条斜线
return render(request, 'dateapp/current_datetime.html', {'current_date': now})
include模板标签
- {% include %},
{% include 'nav.html' %}
- 作用是引入另一个模板的内容。它的参数是要引入的模板的名称,可以是变量,也可以是硬编码的字符串(放在引号里,单双引号都行)
模板继承
定义有区别的片段
- 父模板
{% block 块名称,用于区分块 %}子模板可以覆盖块的内容、向块中添加内容,或者原封不动。{% endblock %}
- 子模块
{% extends "父模板的名称" %} # 声明子模块,加载父模块,要出现在子模块的第一个模板标签,使用与 get_template() 相同的方法加载
{% block 要覆盖的块名称 %}覆盖的内容{% endblock %}
从父模板中的块里获取内容,使用 {
{ block.super }} ,这是一个“魔法”变量,提供父模板中渲染后的文本。向块中添加内容,而不是完全覆盖时就可以这么做