一、 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>