一、概要
对于模版,其实就是读取模版(其中嵌套着模版标签),然后将模型中获取的数据插入到模版中,最后将信息返回给用户。
二、模板应用
1、说明
只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板
本质就是html+模板语法
2、为什么要使用模板
- 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 网站设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。
- Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。
- 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。
2、基本使用
- views.py
class User: def __init__(self, name=None, age=0): self.name = name self.age = age # views def index(request): title = "Hello Django" num = 110 li = [1, 2, 3, 4, 5] dic = {'name': '小明', 'age': 20} user1 = User(name='小明') user2 = User(name='小红') user_list = [user1, user2] context = { 'num': num, 'title': title, 'li': li, 'dic': dic, 'user': user1, 'user_list': user_list, } return render(request, 'home/index.html', context)
- templates/home/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/js/jquery-3.3.1.js"></script> </head> <body> <ul> <li>数字:{{ num }}</li> <li>字符串:{{ title }}</li> <li>列表:{{ li.0 }}</li> <li>列表:{{ li.1 }}</li> <li>列表:{{ li.2 }}</li> <li>字典:{{ dic.name }}</li> <li>字典:{{ dic.age }}</li> <li>对象:{{ user.name }}</li> <li>对象:{{ user.age }}</li> <li>列表:{{ user_list.1.name }}</li> </ul> <h3>遍历li的值</h3> {% for item in li %} <p>{{ item }}</p> {% endfor %} <h3>遍历列表,去对象的值</h3> {% for user in user_list %} 用户名:<span>{{ user.name }}</span> 密码:<span>{{ user.age }}</span> {% endfor %} <h3>遍历字典,</h3> {% for user in dic.items %} 用户名:<span>{{ user.name }}</span> 密码:<span>{{ user.age }}</span> {% endfor %} <h3>遍历列表,去对象的值: 倒序</h3> {% for user in user_list reversed %} 用户名:<span>{{ user.name }}</span> 密码:<span>{{ user.age }}</span> {% endfor %} </body> </html>
三、模板语法
1、变量--{}
1.1、 {}语法
- 语法格式
{{ }}
- 举个栗子
#views.py def index(request): return render(request, 'home/index.html', {'content','模板语法'})
<body> <p>{{ content }}</p> </body>
1.2、语法
- 语法格式
对象.变量名
- 应用
字典查询(Dictionary lookup) 属性或方法查询(Attribute or method lookup) 数字索引查询(Numeric index lookup) 对象.方法名(必须无参)
- 举个栗子
见基本
2、标签--{% tag %}
标签看起来像是这样的:
{% tag %}
。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如
{% tag %} ...
标签 内容 ... {% endtag %})
2.1、for
- 语法格式1
{% for 元素 in 可迭代对象 %} {{ 元素 }} {% endfor %} {% for 元素 in 可迭代对象 %} {{ 元素. 属性}} {% endfor %}
- 语法格式2
{% for 元素 in 可迭代对象 reversed%} {{ 元素. 属性}} {% endfor %}
- 语法格式3
{% for 元素 in 可迭代对象 %} <p>{{元素.属性}}</p> {% empty %} <p>空元素</p> {% endfor %}
- 语法格式4
{% for item in 可迭代对象 %} # 默认从1开始计数 {{ forloop.counter }} # 表示从0开始计数 {{ forloop.counter0 }} # {{ forloop.recounter }} {{ forloop.recounter0 }} # 判断是否是第一个元素 {{ forloop.first }}: {{ item }} # 判断是否是最后一个元素 {{ forloop.last }}: {{ item }} {% endfor %}
- 示例代码
{% for item in li %} <h3>计算器</h3> 计数默认:<span>{{ forloop.counter0 }}</span> 计数倒序:<span>{{ forloop.revcounter }}</span> 是否第一项:<span>{{ forloop.first }}</span> 是否是最后一项:<span>{{ forloop.last }}</span> {% endfor %}
{% for link in links %} {{ link }} {% if not forloop.last %} | {% endif %} {% endfor %}
2.2、if
- 语法格式
{% if 条件表达式1 %} {% elif 条件表达式2 %} {% else %} {% endif %}
- 示例代码
{% if num > 100 or num < 0 %} <p>无效</p> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <p>差</p> {% endif %}
2.3、csrf_token
- 说明
用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效。其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。
注意:在settings中的中间件MIDDLEWARE中配置打开
'django.middleware.csrf.CsrfViewMiddleware', - 语法格式
{%csrf_token%}
- 示例代码
<form action="{% url "bieming"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
2.4、url
- 说明
引用路由配置的地址 - 语法格式
{% url 'name' %}
- 举个栗子
url的用法也很简单,只要在urlpatterns里使用它,附加一个name urlpatterns = [ url(r'^home$','index' ,name="test_url"), ]
<a href="{% url 'test_url' %}"></a>
2.5、static
- 说明
引用静态文件 - 使用步骤
1、在首部使用模板标签{% load staticfiles %}来说明一下内容,将载入静态文件;
2、使用{% static 'css/style.css' %}来指明CSS框架文件的存放位置;
3、若html文件中,出现需要引用静态文件的地方,都需要用static来替换。 - 示例代码
<!DOCTYPE html> <html lang="en"> {% load staticfiles %} <head> <meta charset="UTF-8"> <title>Title</title> <link href="{% static 'css/common.css'%}" rel='stylesheet'> <script src="{% static 'js/jquery-3.3.1.js'%}"></script> </head> <body> </body> </html>
模板标签
- 说明
该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。 - 语法
{% include '引入的模板名' %}
- 示例代码
top.html <div> <a href="{% url 'login' %}">请登录</a> <a href="{% url 'register' %}">免费注册</a> </div>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'top.html' %} </body> </html>
3、过滤器 {{obj|filter__name:param}}
可以通过过滤器来修改变量的显示,过滤器的形式是:{{ variable | filter }},管道符号'|'代表使用过滤器
过滤器能够采用链式的方式使用,例如:{{ text | escape | linebreaks }}
过滤器还可以带参数,例如: {{ bio|truncatewords:30 }}
过滤器的参数中如果带有空格,那么需要用引号引起来,例如:{{ list | join : ", "}}
django中30个内建的过滤器
3.1、add
- 说明
给变量加上相应的值
过滤器首先会强制把两个值转换成Int类型。如果强制转换失败, 它会试图使用各种方式吧两个值相加。它会使用一些数据类型 (字符串, 列表, 等等.) - 语法格式
{{ value|add:"值" }}
- 举个栗子
#st = 'hello' {{ st|add:"world" }}
3.2、default
- 说明
如果一个变量是False或者为空,使用给定的默认值。否则,使用变量的值 - 语法格式
{{ value|default:",默认值" }}
- 举个栗子
title = '' {{ title|default:",默认值" }}
3.3、length
- 说明
返回值的长度。它对字符串和列表都起作用 - 语法格式
{{ value|length }}
- 举个栗子
li = ['a', 'b', 'c', 'd'] {{ li|length }} #4
3.5、date
- 说明
按指定的格式字符串参数格式化 date 或者 datetime 对象 - 语法格式
{{ value|date:"日期格式" }}
- 举个栗子
#如果 now_time = datetime.datetime.now() {{ now_time|date:"Y-m-d H:i:s" }}
4、自定过滤器
4.1、说明
在内置的方法满足不了我们的需求的时候,就需要自己定义属于自己的方法了,自定义方法分别分为filter和simple_tag
4.2 、区别
- 传参:
- filter默认最多只支持2个参数:可以用{{value|fun:"p1, p1, p3" }}这种形式将参数传递个函数
- simple_tag支持多个参数:{% fun p1 p2 p3 p4 %} 有多少就写多少
- 模板语言if条件:
- filter支持if
# 函数的结果作为if语句的条件 {% if value|f1 %} <h1>True</h1> {% else %} <h1>False</h1>
- simple_tag: 不支持模板语言if条件`
4.3、步骤
- 在settings中的INSTALLED_APPS,注册app
- 在app中创建templatetags目录,目录名必须为templatetags
- 创建一个自定义的custom_tags.py
from django import template from django.utils.safestring import mark_safe # register的名字是固定的,不可改变 register = template.Library() # 过滤器 @register.filter def test_filter(value, param): return value + param @register.filter def test_filter2(value, param1,param2): return value + param1 + param2 # 标签 @register.simple_tag def multi_tag(value, p2, p3, p1): return value * p2 * p3 * p1 @register.simple_tag # 标签 def my_input(id, arg): result = "<input type='text' id='%s' class='%s' />" % (id, arg,) return mark_safe(result)
- 在使用自定义simple_tag和filter的html文件中导入之前创建的 custom_tags.py
- 在引用模板中导入:{% load custom_tags %}
- 在模板中使用
{# 使用filter方式调用自定义方法 #} <!-- 将当做参数传递给test_filter1函数进行处理 处理方式 test_filter2(test_filter1) --> <p>{{ test_filter1|test_filter2}}</p> !-- 将test_filter当做参数传递给test_filter2函数进行处理,接受2个参数 处理方式 <p>{{ test_filter1|test_filter2:"xxx" }}</p> {# 使用simple_tag方式调用自定义方法 #} <!-- 将k1当做参数传递给multi_tag函数进行处理,接收多个参数 处理方式 multi_tag("处理的值", "参数1" "参数2" "参数3") --> <p>{% multi_tag "处理的值" "参数1" "参数2" "参数3" %}</p>
四、模版继承
1、说明
Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您网站中的全部元素,并且可以定义能够被子模版覆盖的块
2、相关语法
- 继承语法
{% extends "母版名称" %}
- 块语法
{% block 块名称 %} 重写内容 {% endblock %}
3、示例代码
- 母版
<!DOCTYPE html> <html lang="en"> {% load staticfiles %} <head> <meta charset="UTF-8"> <title> {% block page_title %} {% endblock %} </title> {% block page_css %} {% endblock %} {% block page_jq %} {% endblock %} </head> <body> <div> <div id="head"> {% block page_head %} {% endblock %} </div> <div id="content"> {% block page_content %} {% endblock %} </div> <div id="footer"> {% block page_footer %} {% endblock %} </div> </div> </body> </html>
- 子模板
{% extends 'base.html' %} {% block page_jq %} jq代码 {% endblock %} {% block page_head %} 头部HTML代码 {% endblock %} {% block page_content %} 主体HTML内容代码 {% endblock %} {% block page_footer %} 底部HTML内容代码 {% endblock %}
4、总结
- 如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
- 在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
- 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
- 如果需要获取父模板中的block 的内容,可以使用{{ block.super }} 变量。如果你想要在父block 中新增内容而不是完全覆盖它,它将非常有用。