Django模版系统
1. 常用语法
Django模版中最常用的两种特殊符号:{{ }}
和{% %}
{{}}
表示变量,在模版渲染的时候替换成具体的值
{%%}
表示逻辑相关的操作,即一些逻辑语句
1.1 变量
模版中引用变量的方法:{{变量名}}
变量名是由字母数字和下划线组成
点(.)
在模版语言中有特殊的含义,用来获取对象/变量的响应属性值
示例
view视图文件中的代码:
from django.shortcuts import render
import datetime
def index(request):
l = [11, 22, 33]
d = {"name": "tom","age":19}
master = "ADMINistrator"
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def dream(self):
return "{} is dream...".format(self.name)
Vincent = Person(name="Vincent", age=18)
Jack = Person(name="Jack", age=29)
Tony = Person(name="Tony", age=33)
person_list = [Vincent,Jack,Tony]
return render(
request,
"index.html",
{"l": l,
"d": d,
"master":master,
"person_list": person_list,
"filesize01":100,
"filesize02":1024,
"filesize03":1024*1024,
"now":datetime.datetime.now(),
'url':'<a href="https://baidu.com">百度</a>'
}
)
template模版文件中的写法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>列表</h1>
l列表: {{ l }}
<br>
l列表0索引位置的元素: {{ l.0 }} {# 按索引取值,不支持负向索引 #}
<br>
<h1>字典</h1>
d字典: {{ d }}
<br>
d字典中key为name的值: {{ d.name }}
<br>
字典中的其他方法: {{ d.keys }} --- {{ d.values }} --- {{ d.items }}
<br>
<h1>实例化后的对象</h1>
对象的属性使用: {{ person_list.0.name }} {{ person_list.0.age }}
<br>
对象的方法使用: {{ person_list.0.dream }}
</body>
</html>
web页面显示结果:
列表
l列表: [11, 22, 33]
l列表0索引位置的元素: 11
字典
d字典: {'age': 19, 'name': 'tom'}
d字典中key为name的值: tom
字典中的其他方法: dict_keys(['age', 'name']) --- dict_values([19, 'tom']) --- dict_items([('age', 19), ('name', 'tom')])
实例化后的对象
对象的属性使用: Vincent 18
对象的方法使用: Vincent is dream...
注意:
当模版系统遇到一个(.)
时,会按照如下的顺序去查询:在字典中(按key)查询–>(对象的)属性或者方法–>数字索引(另外,属性的优先级 > 方法的优先级)
1.2 Filters
过滤器,用来修改变量的显示结果
1)语法:
{{变量|filter_name}}
{{变量|filter_name:参数}}
注意:":"所有没有空格
2)内置过滤器
view视图函数仍取1.1章节的内容
-
default
若变量值没传,则显示指定的默认内容
{{变量|default:"can not find this variable"}}
如果变量的值没传的话,就显示"can not find this variable";
变量的值没传包括两种情况:1.变量不存在 2.变量值为空(空字串、空列表、空字典等)
-
filesizeformat
将格式化为一个“人类可读“的文件尺寸,如100bytes,10KB,2.2M等
{{value|filesizeformat}}
-
add
给变量加参数,可以实现:数字的加减法、字符串的拼接、列表的拼接
参数可以是数字、字串、列表 或者赋以上值之后的变量
{{value|add:参数}}
-
lower
小写
{{value|lower}}
-
upper
大写
{{value|upper}}
-
title
标题,即首字母大写
{{value|title}}
-
ljust
左对齐
{{value|ljust:"10"}}
以空格为单位
-
rjust
右对齐
{{value|rjust:"10"}}
-
center
居中
{{value|center:"15"}}
-
length
返回value的长度,如列表、字符串
{{value|length}}
-
slice
切片
{{value|slice:"2:-1"}}
-
first
取第一个元素
{{value|first}}
-
last
{{value|last}}
-
join
使用字符串拼接列表
{{value|join:"X"}}
-
truncatechars
截断,如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列("…")结尾
参数:截断的字符数(包括最后三个点,每个点占一个字符位)
{{value|truncatechars:9}}
如上,相当于取了value字符串中前6个字符+最后3个".",总共9个字符数
-
date
日期格式化
{{ value|date:"Y-m-d H:i:s"}}
可格式化输出的字符:https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#date
注意:由于可能有多处日期需格式化,因此可以统一将格式化的标准配置在settings.py文件中
USE_L10N = False DATETIME_FORMAT = 'Y-m-d H:i:s' DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s'
-
Safe
Django的模版中考虑到安全问题,会对HTML标签和JS等语法标签进行自动转义。但是有时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转移的话,显示的就是保护HTML标签的源文件。
为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器
{{value|safe}}
的方式告诉Django这段代码是安全的不必转义{{value|safe}}
3)过滤器使用示例
view视图函数内容
通1.1章节内容
template模版内容
<h3>过滤器</h3>
default: {{ mlg|default:"nothingthis" }}
<br>
filesizeformat: {{ filesize01 }} -- {{ filesize01|filesizeformat }} -- {{ filesize02|filesizeformat }} -- {{ filesize03|filesizeformat }}
<br>
and: {{ 2|add:2 }} -- {{ "hello"|add:"world" }} -- {{ l|add:l }}
<br>
lower: {{ master|lower }}
<br>
upper: {{ master|upper }}
<br>
title: {{ "title"|title }}
<br>
length: {{ "hello"|length }} -- {{ l|length }} -- {{ l|add:l|length }}
<br>
slice: {{ l|slice:'::2'}} -- {{ l|slice:'::-1' }}
<br>
first: {{ l|first }}
<br>
last: {{ l|last }}
<br>
join: {{ master|join:"//" }} -- {{ "hello"|join:"X" }} -- {{ "XY"|join:l }} -- {{ l|join:"X" }}-- {{ "X"|join:"Y" }}
<br>
truncatechars: {{ master|truncatechars:6 }} -- {{ "helloworld"|truncatechars:8 }} -- {{"123456789"|truncatechars:4 }} -- {{ "12 3 45 67 8 9"|truncatechars:7 }} -- {{ "离离 原上 草一 岁一 枯荣"|truncatechars:4 }}
<br>
date: {{ now }} -- {{ now|date:'Y-m-d H:i:s' }}
<br>
self: {{ url }} -- {{ url|safe }}
浏览器显示结果
过滤器
default: nothingthis
filesizeformat: 100 -- 100 bytes -- 1.0 KB -- 1.0 MB
and: 4 -- helloworld -- [11, 22, 33, 11, 22, 33]
lower: administrator
upper: ADMINISTRATOR
title: Title
length: 5 -- 3 -- 6
slice: [11, 33] -- [33, 22, 11]
first: 11
last: 33
join: A//D//M//I//N//i//s//t//r//a//t//o//r -- hXeXlXlXo -- X[11, 22, 33]Y -- 11X22X33-- X
truncatechars: ADM... -- hello... -- 1... -- 12 3... -- 离...
date: Feb. 20, 2020, 7:04 a.m. -- 2020-02-20 07:04:14
self: <a href="https://baidu.com">百度</a> -- 百度
1.3 自定义filter
自定义过滤器,只是带着一个或两个参数的Python函数
变量的值,不一定是一个字符串;
参数的值,可以有一个默认值,或者省略
例如,在过滤器{{var|foo:"bar"}}
中,过滤器foo将传递变量var和参数"bar"
自定义filter代码文件所在位置
app01/
__init__.py
models.py
templatetags/ # 在app01下面新建一个package package
__init__.py
app01_filters.py # 建一个存放自定义filter的py文件
views.py
编写自定义filter
from django import template
register = template.Library()
@register.filter
def fill(value, arg):
return value.replace(" ", arg)
@register.filter(name="addSB")
def add_sb(value):
return "{} SB".format(value)
使用自定义filter
{# 先导入我们自定义filter那个文件 #}
{% load app01_filters %}
{# 使用我们自定义的filter #}
{{ somevariable|fill:"__" }}
{{ d.name|addSB }}
1.4 Tags
1)常用的标签
-
for
<ul> {% for i in l %} <li> {{ forloop.counter }} - {{ i }} </li> {% endfor %} </ul>
for循环可用的一些参数:
Variable Description forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(到1结束) forloop.revcounter0 当前循环的倒序索引值(到0结束) forloop.first 当前循环是不是第一次循环(返回布尔值) forloop.last 当前循环是不是最后一次循环(返回布尔值) forloop.parentloop 本层循环的外层循环 -
for … empty
<ul> {% for i in user_list %} <li> {{ i }} </li> {% empty %} <li>这里的结果为空</li> {% endfor %} </ul>
当user_list循环结果为空时,就走
{% empty %}
的逻辑(比如,user_list列表不存在时) -
If … elif … else
<ul> {% if user_list %} {{ user_list }} {% elif 1 > 3%} 测试 {% else %} {{ l }} {% endif %} </ul>
-
if … else
<ul> {% if user_list %} {{ user_list }} {% else %} {{ l }} {% endif %} </ul>
注意:
if语句不支持直接的算数运算(可后台计算,或者自定义过滤器)
if语句不支持连续判断(如10>5>1)
if语句支持 and、or、==、>、<、!=、<=、>=、in、not in、 is、is not 判断
-
with
定义一个中间变量,相当于把某个变量重新定义一个变量名
{% with person_list.0.name as nameFirst %} {{ nameFirst }} {% endwith %}
{% with nameSecond=person_list.1.name %} {{ nameSecond }} {% endwith %}
2)标签使用示例
视图文件内容
同1.1内容
模版文件内容
<h3>Tags</h3>
<h4>for</h4>
<ul>
{% for i in l %}
<li>
{{ forloop.counter }} - {{ i }}
</li>
{% endfor %}
</ul>
<h4>for empty</h4>
<ul>
{% for i in user_list %}
<li>
{{ i }}
</li>
{% empty %}
<li>这里的结果为空</li>
{% endfor %}
</ul>
<h4>if...elif...else</h4>
<ul>
{% if user_list %}
{{ user_list }}
{% elif 1 > 3%}
测试
{% else %}
{{ l }}
{% endif %}
</ul>
<h4>with</h4>
{% with person_list.0.name as nameFirst %}
{{ nameFirst }}
{% endwith %}
<br>
{% with nameSecond=person_list.1.name %}
{{ nameSecond }}
{% endwith %}
浏览器显示结果
1.5 csrf_token
此标签用于跨站请求伪造保护(跨站请求伪造保护参考:百度百科之跨站请求伪造)
在页面的form表单里面写上{% csrf_token %}
即可
<form action="" method="post">
{% csrf_token %}
<p>
出版社名称:<input type="text" name="pub_name"> <span>{{ error }}</span>
</p>
<p>
<button>提交</button>
</p>
</form>
1.6 注释
{# ... #}
2.母版
母版类似python中的父类,会把web页面的公共部分集成在母版文件中,而其他自页面可以直接继承母版内容,并自定义填充替换子页面的特定内容
我们通常会在母板中定义页面专用的CSS块和JS的block块,方便子页面替换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>出版社展示页面</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
{% block css %}
{% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active"><a href="/publisher_list/">出版社列表 <span class="sr-only">(current)</span></a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Export</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{% block content01 %}
{% endblock %}
</div>
</div>
</div>
{% block js %}
{% endblock %}
</body>
</html>
block块里的内容,其他页面继承母版之后,可以任意替换填充
3. 继承母版
继承母版,在子页面中最上方通过下述语法继承母版(母版名称带双引号)
{% extends 'base.html' %}
{% extends 'base.html' %}
{% block content01 %}
<h>新增出版社</h>
<form action="" method="post">
{% csrf_token %}
<p>
出版社名称:<input type="text" name="pub_name"> <span>{{ error }}</span>
</p>
<p>
<button>提交</button>
</p>
</form>
{% endblock %}
4. 块(block)
在母版中,通过以下语法来定义“块”
{% block content01 %}
{% endblock %}
在子页面中,通过定义和母版中相同名称的“块”,来替换对应位置的内容
{% block content01 %}
子页面中自定义的内容,可替换、填充母版中的content01块
{% endblock %}
5. 组件
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的html文件中,然后在需要使用的地方按如下语法导入即可
{% include 'navbar.html' %}
6. 静态文件相关
{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
使用/引入js文件时:
{% load static %}
<script src="{% static "mytest.js" %}"></script>
某个文件多处被用到可以存为一个变量
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>
示例
固定的css路径
<head>
<meta charset="UTF-8">
<title>出版社展示页面</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
<link rel="stylesheet" href="/static/css/dashboard.css">
</head>
静态文件引用(相对路径)
<head>
<meta charset="UTF-8">
<title>出版社展示页面</title>
{% load static %}
<link rel="stylesheet" href="{% static "/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" %}">
<link rel="stylesheet" href="{% static "/css/dashboard.css" %}">
</head>