模板层
用法
views.py
:
def demo(request):
content = "demo"
content_list = ["1", "2", "3"]
# 1. 找到 templates
# 2. 读取文件内容 + 传入参数 -> 模板渲染(替换)
# 3. 封装到 HttpResponse 请求体中
# 4. 返回给用户
return render(request, "demo.html", {"content": content, "content_list": content_list})
settings.py
:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 根据此处寻找 html 的位置
# 优先 DIRS ,如果没找到,就去 APP_DIRS ,按顺序查找,即同名 html 返回排前面的
# 一般在 BASE_DIR / 'templates' 里面放通用的 html 文件
# app 下面创建的 templates 放单独的 html 文件
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
模板语法
注释
{# content #}
循环语句
<ul>
{% for item in content_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
条件语句
{% if item == "a" %}
{# forloop 用于获取循环信息 #}
<li><b>{{ forloop.counter }}, {{ item }}</b></li>
{% else %}
<li>{{ forloop.counter }}, {{ item }}</li>
{% endif %}
过滤器
{{ request.method|lower }}
导入语句
{# 多用于模块化和代码复用 #}
{% include 'other.html' %}
继承语句
- 根模板
base.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
{# {% block xxx %} 用来挖块 #}
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div>
{% block content %}{% endblock %}
</div>
</body>
</html>
- 子模板
{# {% extends 'xxx.html' %} 制定根模板 #}
{% extends 'base.html' %}
{# {% block xxx %} 用来填块 #}
{% block title %}title{% endblock %}
{% block content %}
<h1>content</h1>
{% endblock %}
导入静态文件
{% static 'path/to/file' %}
<script src="{% static 'js/main.js' %}"></script>
自定义模板函数
固定步骤:
-
注册
app
-
app
目录下创建文件夹templatetags
-
文件夹下创建函数
my_tags.py
-
from django.template.library import Library register = Library()
-
定义函数并添加装饰器
5.1 simple_tag()
-> 返回值
- 定义函数
@register.simple_tag()
def tag_func(v1):
return f"My tag: {v1}"
- html 中调用
{% load my_tags %}
{# 如果有多个参数,用 空格 分隔 #}
{% tag_func "success" %}
- html 输出
My tag: success
5.2 inclusion_tag()
-> 返回 html 标签(局部渲染)
- 定义函数
@register.inclusion_tag("inc.html")
def tag_func2(v1):
return {"v1": v1}
- 编写
inc.html
<ul>
{% for item in v1 %}
<li>{{ item }}</li>
{% endfor %}
</ul>
- html 中调用
{% load my_tags %}
{% tag_func2 "abc" %}
{% tag_func2 content_list %}
- 注意:不能直接传递 列表 ,要传递 列表 必须放在变量里面
5.3 filter
-> 对参数直接操作并返回结果(过滤器,常用于 if 条件判断)
- 定义函数
@register.filter
def tag_func3(v1):
return v1.upper()
- html 中调用
{% load my_tags %}
{# 如果有两个参数,语法格式为 "abc"|tag_func3:"xyz" #}
{# 如果有多个参数,建议用 simple_tag() #}
{{ "abc"|tag_func3 }}
- html 输出
ABC
注意点:关于参数替换
<script>
{# 传入参数 {"info": "xxx"} #}
alert({{ info }}) {# 报错 #}
alert("{{ info }}") {# 成功,并成功替换 #}
</script>
{# main.js 里面有 alert("{{ info }}") #}
<script src="{% static 'js/main.js' %}"></script> {# 成功,但没有替换 #}
-
报错原因:
- Django 模板会将
{{ info }}
渲染为文本插入到 HTML 代码中,而不加引号时,JavaScript 期望的info
是一个变量或对象,而不是字符串。
- Django 模板会将
-
没有替换的原因:
-
Django 模板语言只对 HTML 模板文件起作用,不能直接解析
.js
文件中的模板变量。 -
解决方案:
<script> var info = "{{ info }}"; </script> <script src="{% static 'js/main.js' %}"></script>
-
补充:Django 自带过滤器
字符串处理
-
add
:将值与给定的字符串相加(连接)。{{ "Hello, " |add:"World!" }} <!-- 输出: Hello, World! -->
-
capfirst
:将字符串的第一个字母大写。{{ "django" |capfirst }} <!-- 输出: Django -->
-
center
:将字符串居中,填充空格。{{ "django" |center:10 }} <!-- 输出: " django " -->
-
cut
:移除指定的字符串。{{ "hello world" |cut:" " }} <!-- 输出: helloworld -->
-
join
:用指定字符串连接列表元素。{{ my_list|join:", " }} <!-- 假设 my_list 是 ["a", "b", "c"],输出: "a, b, c" -->
-
length
:返回字符串或列表的长度。{{ "django" |length }} <!-- 输出: 6 -->
-
lower
:将字符串转换为小写。{{ "Django" |lower }} <!-- 输出: django -->
-
upper
:将字符串转换为大写。{{ "Django" |upper }} <!-- 输出: DJANGO -->
-
truncatechars
:截断字符串到指定的字符数,并在结尾加上省略号。{{ "This is a long string" |truncatechars:10 }} <!-- 输出: This is... -->
-
urlencode
:对字符串进行 URL 编码。{{ "hello world" |urlencode }} <!-- 输出: hello%20world -->
列表与字典操作
-
dictsort
:对字典或对象列表按指定键排序。{{ my_list|dictsort:"name" }} <!-- 按 name 排序 -->
-
first
:获取列表中的第一个元素。{{ my_list|first }} <!-- 假设 my_list 是 ["a", "b", "c"],输出: a -->
-
last
:获取列表中的最后一个元素。{{ my_list|last }} <!-- 输出: c -->
-
length_is
:如果长度等于给定值,则返回 True,否则 False。{{ my_list|length_is:3 }} <!-- 输出: True/False -->
-
slice
:对列表进行切片。{{ my_list|slice:":2" }} <!-- 获取前两个元素 -->
数值处理
-
addslashes
:在字符串中的特殊字符前添加反斜杠。{{ "John's" |addslashes }} <!-- 输出: John\'s -->
-
floatformat
:格式化浮点数,保留指定小数位数。{{ 3.14159 |floatformat:2 }} <!-- 输出: 3.14 -->
-
default
:如果变量不存在或为空,则返回指定默认值。{{ value|default:"N/A" }}
-
default_if_none
:如果变量为None
,则返回默认值。{{ value|default_if_none:"N/A" }}
-
divisibleby
:判断一个数字是否能被另一个数整除。{{ value|divisibleby:3 }} <!-- 输出: True/False -->
-
yesno
:将布尔值转换为自定义的输出。{{ value|yesno:"yes,no,maybe" }} <!-- 输出: yes/no/maybe -->
日期和时间
-
date
:格式化日期为指定格式。{{ value|date:"Y-m-d" }} <!-- 输出: 2024-09-22 -->
-
time
:格式化时间为指定格式。{{ value|time:"H:i:s" }} <!-- 输出: 14:30:00 -->
-
timesince
:显示从指定时间点到当前的时间差。{{ value|timesince }} <!-- 输出: 2 days ago -->
-
timeuntil
:显示从当前时间到指定时间的时间差。{{ value|timeuntil }} <!-- 输出: 3 hours -->
逻辑与比较
-
ifnull
:如果变量为None
,则返回 True,否则 False。{{ value|ifnull }}
-
length_is
:判断一个对象的长度是否等于给定值。{{ value|length_is:5 }} <!-- 输出: True/False -->
-
filesizeformat
:将文件大小格式化为可读格式(如 KB, MB)。{{ value|filesizeformat }} <!-- 输出: 2.4 MB -->