一、 Template概述
1.1 模板作用
- 呈现给用户界面; 实现MTV中TV的解耦;
- VT 有着N:M的关系; 一个View可以调用任意Template, 一个Template可以被任意View使用
1.2 模板内容
- HTML静态代码
- 动态插入的代码段(变量、运算、转换和逻辑)
二、 模板加载处理流程
- 加载: 读取指定的html文件
- from django.template import loader
- template = loader.get_template('index.html')
- 渲染: 以context设置的数据,处理html文件中模板的语句和变量,生成html网页内容
- html = template.render(context) # context是一个dict类型对象
- 加载+渲染:
- html = loader.render_to_string("index.html", context)
def user_list3(request: HttpRequest):
users = UserEntity.objects.all()
msg = '最佳创业团队'
# 加载模板
template = loader.get_template('user/list2.html')
# 渲染模板
html = template.render(context={'msg': msg, 'users': users})
return HttpResponse(html, status=200)
def user_list3(request: HttpRequest):
users = UserEntity.objects.all()
msg = '最佳创业团队'
html = loader.render_to_string('user/list2.html', locals(), request)
return HttpResponse(html, status=200)
三、 模板语法
3.1 变量 {{ var }}
变量: 遵循命名规范
点语法(.): 获取属性 car.name ; 调用方法: 不能传递参数 / 索引 cars.0.name / 字典 cars.key
3.1.1 读取列表中的变量 users.2; 读取变量的属性 user.name
<body>
<h3>{{ msg }}</h3>
<p style="color: green;">
第三个用户名: {{ users.2.name }}
</p>
<ul>
{% for user in users %}
<li>{{ user.id }} | {{ user.name }} | {{ user.age }} | {{ user.phone }}</li>
{% endfor %}
</ul>

3.1.2 字典获取key和value
<p style="color: red;">
今天请客人ID: {{ error_index }}
</p>
<p style="color: white; ">
<span>VIP:</span>
<span>{{ vip.name.upper }} - {{ vip.money }}</span>
</p>
<ul>
{% for key, value in vip.items %}
<li>{{ key }} = {{ value }}</li>
{% endfor %}
</ul>
3.1.3 变量的索引
def user_list3(request: HttpRequest):
users = UserEntity.objects.all()
error_index = random.randint(0, users.count()-1)
<p style="color: red;">
今天谁请客: {{ users.error_index.name }} # 这样不起作用
</p>
3.2 表达式标签 {% %}
for...in 循环
- 遍历集合(数组,列表): {% for 变量 in 列表 %} 语句1 {% empty %} 语句2 {% endfor %}
- forloop: counter 第几次循环,从1开始 / counter0 / revcounter / revcounter0 / first / last
- empty: 集合为空时的处理; {% empty %} 集合对象不能为None, 但是没有元素
- {% cycle "even" "" %}: 轮询的方式选择后面的字符串
if判断
- if表达式: {% if expression %} 语句 {% endif%}; 表达式必须要关闭
- if-else: {% if 表达式 %} 语句 {% else %} 语句 {% endif %}
- if-elif-else: {% if 表达式 %} 语句 {% elif 表达式 %} 语句 {% endif %}
注释
- 单行注释: {# 被注释的内容 #}
- 多行注释: {% comment %} 内容 {% endcomment %}
- 注释的内容在渲染模板之后,不会保留在HTML页面中
ifequal 如果相等 {% ifequal value1 value2%} 语句 {% endifequal %}
ifnotequal 如果不相等
3.2.1 forloop.counter 是从 1 开始, error_index 是从0开始
<ul>
{% for user in users %}
<li>{{ forloop.counter }} - {{ user.id }} | {{ user.name }} | {{ user.age }} | {{ user.phone }}</li>
{% if forloop.counter == error_index %}
<p style="color: red;">
今天谁请客呢: {{ user.name }}
</p>
{% endif %}
{% endfor %}
</ul>
{% if forloop.counter0 == error_index %}

3.2.2 if 判断 、 for循环、 cycle
<head>
<meta charset="UTF-8">
<title>Django Index主页</title>
{% include 'base_css.html' %}
<style>
.even { background-color: lightgoldenrodyellow; }
.red { background-color: red; }
.blue { background-color: blue; }
.green { background-color: green; }
</style>
</head>
<table class="table table-bordered table-responsive table-hover">
<thead>
<th>ID</th>
<th>账号</th>
<th>真实姓名</th>
<th>手机号</th>
</thead>
<tbody>
{% if users %}
{% for user in users %}
<tr class="{% cycle "even" "" %}">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.realprofile.real_name }}</td>
<td>{{ user.phone }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4">无数据</td>
</tr>
{% endif %}
</tbody>

3.2.3 cycle 遍历
<tr class="{% cycle "red" "blue" "green" %}

3.2.4 empty
<ul>
{% for name in names %}
<li>{{ name }}</li>
{% empty %}
<option>空</option>
{% endfor %}
</ul>
3.2.5 ifequal
<tr {% ifequal forloop.counter 3 %} class="even" {% else %} class="red" {% endifequal %}>

3.3 过滤器/逻辑计算
数值运算
- 加减: 通过加上负数的形式实现减法; {{ store.years|add:5 }} {{ store.years|add:-2 }}
- 乘除: {% widthratio 变量 分母 分子 %} 例:{% widthratio price 10 1 %} price 的 10分之1
- 整除: {% if num|divisibleby:2 %}
字符串操作
- lower: {{ p.pname|lower }}
- upper: {{ p.pname|upper }}
- capfirst:{{ value|capfirst }} value的第一个字符转换成大写
- cut: {{ value|cut:arg }} 从给定value中删除所有arg的值
- join: {{ value|join:'-'}} {{ value|join:'-'|escape}} 对iterable进行连接
<tr {% ifequal forloop.counter|divisibleby:2 0 %} class="even" {% endifequal %}> # counter/2余数等于0

3.4 default 默认值
格式: {{ value|default:val }} {{ store.address|default:'无'}}
3.5 日期时间
根据指定格式转换日期为字符串, {{ dateVal | date:'Y-m-d H:i:s a'}}
格式: F:月份 / g:Hour(1-12)不带前缀0 / G:Hour(0-23)不带前缀0 / l:星期几 / j: 1-31 不带前缀0
{{ now|date: "Y-m-d" }} # 冒号(:) 后面有空格,报错
django.template.exceptions.TemplateSyntaxError: Could not parse the remainder: ': "Y-m-d"' from 'now|date: "Y-m-d"'
3.6 HTML转义
- escape: 保留原始字符串, "<"之类的符号转换成 < [< <] [> >] ['] ["] [& &]
- 在区域开启escape: {% autoescape on/off %} {% endautoescape %}
- 将接收到的数据当前普通字符串处理还是当成HTML代码来渲染
- 渲染成HTML: 不转义 {{ code|safe }} {% autoescape off %} code {% endautoescape %}
- 不渲染成HTML: 转义 {{ code|escape }} {% autoescape on %} code {% endautoescape %}
- 注意: 开发中尽量保持纯文本; 如果进行html渲染,存在被恶意注入风险
{{ info | escape }}
{% autoescape off %}
{{ info }}
{% endautoescape %}
{% autoescape on %}
<pre>
{{ info }}
</pre>
{% endautoescape %}

3.7 其他
- length: {{ value|length }} 返回value的长度
- floatformat
- {{ value|floatformat }} 34.23444 -> 34.2 34.00000 -> 34 34.26000 -> 34.3
- {{ value|floatformat:arg }} 34.23444 -> 34.234 34.00000 -> 34.000 34.26000 -> 34.260
3.7.1 显示文件属性 、数值格式化、 转义
>>> import os
>>> from helloDjango.settings import BASE_DIR
>>> file_path = os.path.join(BASE_DIR, 'mainapp/models.py')
>>> os.stat(file_path)
os.stat_result(st_mode=33206, st_ino=562949954054592, st_dev=1828079847, st_nlink=1,
st_uid=0, st_gid=0, st_size=6674, st_atime=1680343296, st_mtime=1680878778, st_ctime=1680343296)
>>> file_stat = os.stat(file_path)
>>> file_stat.st_size
6674
now = datetime.now()
file_dir = os.path.join(settings.BASE_DIR, 'mainapp/')
# files是一个字典, key是 file_name value是 os.stat(file_dir + file_name)
files = {file_name: os.stat(file_dir + file_name) for file_name in os.listdir(file_dir)
if os.path.isfile(file_dir+file_name)}
price = 19.1356
img_html = "<img width=200 height=200 src='/media/Fruit.jpeg'>"
{% for path, f_stat in files.items %}
<p>
{{ path }} 的文件大小为 {{ f_stat.st_size | filesizeformat }}
</p>
{% endfor %}
<p>
价格: {{ price|floatformat:1 }}
</p>
<p>
{{ img_html|safe }}
</p>

浙公网安备 33010602011771号