模板:
基础知识:
在Django框架中,模板是可以帮助开发者快速⽣成呈现给⽤户⻚⾯的⼯具模板的设计⽅式实现了我们MVT中VT的解耦(M: Model, V:View, T:Template),VT有着N:M的关系,⼀个V可以调⽤任意T,⼀个T可以供任意V使⽤ (MVC: Model,View界⾯,Controller控制器)。
模板处理分为两个过程
-
加载HTML
-
渲染数据 render()
模板主要有两个部分
-
HTML静态代码
-
模板语⾔,动态插⼊的代码段(挖坑,填坑)
模板中的动态代码段除了做基本的静态填充,还可以实现⼀些基本的运算,转换和逻辑
页面分类:
-
静态⻚⾯:⻚⾯数据是本地固定的
-
动态⻚⾯:⻚⾯数据来源于后台服务器
模板中的变量: 视图传递给模板的数据,遵守标识符规则语法: {{ var }}
如果变量不存在,则插⼊空字符串。
jinja2
⽅法不能有参数。
{{ str }}
{{ str.upper }}
{{ str.isdigit }}
{{ dict.key }}
列表,使⽤索引,不允许负索引
items= ['apples', 'bananas', 'carrots']
{{ items.2 }}
标签语句:
模板中的标签
语法 {% tag %}
作⽤
1.加载外部传⼊的变量
2.在输出中创建⽂本
3.控制循环或逻辑
条件语句:
jinja2
if 语句: 格式:
if单分⽀
{% if 表达式 %}
语句
{% endif %} if双分⽀
{% if 表达式 %}
语句
{% else %}
语句
{% endif %}
if多分⽀
{% if 表达式 %}
语句
{% elif 表达式 %}
语句
{% else %}
语句
{% endif %}
判断true或false
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
与或运算:
jinja2
使⽤ and or not
{% if athlete_list and coach_list %}
<p>Both athletes and coaches are available.</p>
{% endif %}
{% if not athlete_list %}
<p>There are no athletes.</p>
{% endif %}
{% if athlete_list or coach_list %}
<p>There are some athletes or some coaches.</p>
{% endif %}
使⽤ in和not in,
{% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{% endif %}
{% if user not in users %}
If users is a list, this will appear if user isn't an element of the list.
{% endif %}
for循环:
jinja2
for 语句:
{% for 变量 in 列表 %}
语句1
{% empty %}
语句2
{% endfor %}
当列表为空或不存在时,执⾏empty之后的语句
jinja2
{{ forloop.counter }} 表示当前是第⼏次循环,从1数数
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{%endfor %}
{{ forloop.counter0}}表示当前是第⼏次循环,从0数数
{{ forloop.revcounter}}表示当前是第⼏次循环,倒着数数,到1停
{{ forloop.revcounter0}}表示当前第⼏次循环,倒着数,到0停
{{ forloop.first }} 是否是第⼀个 布尔值
{% for object in objects %}
{% if forloop.first %}
<li class="first">
{% else %}
<li>
{% endif %}
{{ object }}</li>
{% endfor %}
{{ forloop.last }} 是否是最后⼀个 布尔值
{% for link in links %}
{{ link }}{% if not forloop.last %} | {% endif %}
{% endfor %}
forloop.parentloop
{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
注释:
jinja2
注释:
单⾏注释
{# 被注释掉的内容 #}
多⾏注释
{% comment %}
内容
{% endcomment %}
过滤器:
jinja2
过滤器:
{{ var|过滤器 }}
作⽤:在变量显示前修改
add {{ value|add:2 }}
没有减法过滤器,但是加法⾥可以加负数
{{ value|add:-2 }} lower
{{ name|lower }} upper
{{ my_list|first|upper }} my_list 第一个值变成大写
截断:
{{ bio|truncatechars:30 }}
过滤器可以传递参数,参数需要使⽤引号引起来
⽐如join: {{ students|join:'=' }}
默认值:default,格式 {{var|default:value}}
如果变量没有被提供或者为False,空,会使⽤默认值
根据指定格式转换⽇期为字符串,处理时间的就是针对date进⾏的转换
{{ dateVal | date:'y-m-d' }}
转义:
jinja2
HTML转义
将接收到的数据当成普通字符串处理还是当成HTML代码来渲染的⼀个问题渲染成html:
{{ code|safe }}
关闭⾃动转义
{% autoescape off%} code
{% endautoescape %}
打开⾃动转义转义
{% autoescape on%} code
{% endautoescape %}
案例讲解:
py
from django.shortcuts import render
# Create your views here.
import datetime
from django.shortcuts import render
# 模板
def index(request):
data = {
'name': 'zhangsan',
'age': 3,
'likes': ['movie', 'game', 'code'],
'address': {'city': '深圳', 'province': '广东'},
'stars': [
['化mm', 'mm云', 'mm克'],
['x军', 'mm宏', '一鸣'],
['伯格', 'mm茨', 'mm非'],
],
'dt': datetime.datetime.now(),
'code': '<b>I am a good man</b>',
'code2': '''<script>
var n=3;
while(n--) {
alert('哈哈')
}
</script>''',
}
# 下面的写法都可以
# return render(request, 'index.html', {**data})
return render(request, 'index.html', data)
# 模板继承
# 父模板
def block(request):
return render(request, 'block.html')
# 子模板
def child(request):
return render(request, 'child.html')
# 使用模板(HTML+模板语言): 前后端不分离
py
from django.contrib import admin
from django.urls import path
from App.views import *
urlpatterns = [
path('index/', index),
path('block/', block),
path('child/', child),
path('admin/', admin.site.urls),
]
传参细节:
py
# 用户列表
def user_list(request):
# 获取所有用户数据
users = UserModel.objects.all()
return render(request, 'user_list.html', {'users': users})
这个是我们之前的写法,相当于传递了一个字典,这是因为数据量比较少,如果数据量比较多,就不能这样传递了,如下:
py
# 模板
def index(request):
data = {
'name': 'zhangsan',
'age': 3,
'likes': ['movie', 'game', 'code'],
'address': {'city': '深圳', 'province': '广东'},
'stars': [
['化mm', 'mm云', 'mm克'],
['x军', 'mm宏', '一鸣'],
['伯格', 'mm茨', 'mm非'],
],
'dt': datetime.datetime.now(),
'code': '<b>I am a good man</b>',
'code2': '''<script>
var n=3;
while(n--) {
alert('哈哈')
}
</script>''',
}
return render(request, 'index.html', data) # 这个就是传递的字典
index.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django模板</title>
</head>
<body>
<h2>Django模板</h2>
<hr>
{# 单行注释 #}
{% comment %}
多行注释
多行注释
{% endcomment %}
{# 变量 #}
<p>name: {{ name }}</p>
<p>age: {{ age }}</p>
{# 处理列表,使用 . # }
<p>likes: {{ likes }}</p>
<p>likes.1: {{ likes.1 }}</p>
{# 字典 键值对 #}
<p>address: {{ address }}</p>
<p>address.city: {{ address.city }}</p>
<hr>
<br><br><br><br><br>
<br><br><br><br><br>
</body>
</html>
html
{# 标签 #}
<h3>if语句</h3>
<h4>if单分支</h4>
{% if age < 18 %}
<p>{{ name }} 未成年 </p>
{% endif %}
<h4>if双分支</h4>
{% if age < 18 %}
<p>{{ name }} 未成年 </p>
{% else %}
<p>{{ name }} 成年了! </p>
{% endif %}
<h4>if多分支</h4>
{% if age < 18 %}
<p>{{ name }} 未成年 </p>
{% elif age < 60 %}
<p>{{ name }} 是壮年 </p>
{% else %}
<p>{{ name }} 老年人 </p>
{% endif %}
<h4>结合运算符</h4>
{% if age >= 18 and age < 60 %}
<p>{{ name }} 是壮年,风华正茂,小年轻! </p>
{% endif %}
{% if age < 18 or age >= 60 %}
<p>{{ name }} 未成年或者是老年人! </p>
{% endif %}
{% if 'movie' in likes %}
<p> {{ name }} 喜欢movie! </p>
{% endif %}
<hr>
html
<h3>for循环语句</h3>
{% for like in likes %}
<p>{{ like }}</p>
{% endfor %}
<h4>empty</h4>
{% for like in likes2 %}
<p>{{ like }}</p>
{% empty %}
<p>likes2 为空或者不存在</p>
{% endfor %}
<h4>下标</h4>
{% for like in likes %}
<p>
counter0: {{ forloop.counter0 }},
counter: {{ forloop.counter }},
revcounter0: {{ forloop.revcounter0 }},
revcounter: {{ forloop.revcounter }},
{% if forloop.first %}
<b> - first</b>
{% endif %}
{% if forloop.last %}
<b> - last</b>
{% endif %}
</p>
{% endfor %}
<h4>循环嵌套</h4>
{#{{ forloop.parentloop 是父亲循环 # }
<table border="1" width="400">
{% for star in stars %}
<tr>
{% for s in star %}
<td>
{{ s }}-
{{ forloop.parentloop.counter }} -
{{ forloop.counter }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
html
<h4>过滤器</h4>
<p>age = {{ age }}</p>
<p>age|add:2 = {{ age|add:2 }}</p>
<p>age|add:-2 = {{ age|add:-2 }}</p>
<p>name = {{ name }}</p>
<p>name|last|lower 是将第一个字符取出来 变成大小写 </p>
<p>name|first|upper = {{ name|first|upper }}</p>
<p>name|last|lower = {{ name|last|lower }}</p>
<p>title 首字母大写 </p>
<p>name|title = {{ name|title }}</p>
<p>truncatechars 截断</p>
<p>name|truncatechars:7 = {{ name|truncatechars:7 }}</p>
<p>likes = {{ likes }}</p>
<p> likes|join:'+' 字符串拼接 </p>
<p>likes|join:'+' = {{ likes|join:'+' }}</p>
<p>likes2 = {{ likes2 }}</p>
<p> default 表示默认值 </p>
<p>likes2|default:'swim' = {{ likes2|default:'swim' }}</p>
<p>日期格式化 </p>
<p>dt = {{ dt }}</p>
<p>dt = {{ dt|date:'y-m-d' }}</p>
<p>dt = {{ dt|date:'Y-m-d' }}</p>
html
<h5>html解析</h5>
<p>code|safe 表示对其html做解析,也可以执行js</p>
<p>code = {{ code }}</p>
<p>code|safe = {{ code|safe }}</p>
<p>code2 = {{ code2 }}</p>
{# <p>code2 = {{ code2|safe }}</p> #}
{% autoescape on %}
{{ code }}
{% endautoescape %}
模板继承:
基础知识:
jinja2
模板继承
block:
{% block XXX%} code
{% endblock %}
extends 继承,写在开头位置
{% extends '⽗模板路径' %}
include: 加载模板进⾏渲染
{% include '模板⽂件' %}
{{ block.super }} : 获取⽗模板中block中的内容
py
# 模板继承
# 父模板
def block(request):
return render(request, 'block.html')
# 子模板
def child(request):
return render(request, 'child.html')
py
from django.contrib import admin
from django.urls import path
from App.views import *
urlpatterns = [
path('index/', index),
path('block/', block),
path('child/', child),
path('admin/', admin.site.urls),
]
父模板:
jinja2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{# css #}
{% block extcss %}
{% endblock %}
</head>
<body>
<h2>父模板</h2>
<hr>
{% block head %}
{% endblock %}
<hr>
{% block content %}
<button>我是Content父模板中的按钮</button>
{% endblock %}
<hr>
{% block foot %}
{% endblock %}
{# js #}
{% block extjs %}
{% endblock %}
</body>
</html>
自带只需要对父模板进行填充block即可。
jinja2
{# 继承父模板 #}
{% extends 'block.html' %}
{% block head %}
<div>
<button>Head</button>
</div>
{% endblock %}
{% block content %}
{# 默认情况下,子模板会覆盖父模板的内容 #}
{# 如果想将父模板中block的内容继承,则需要使用block.super #}
{{ block.super }}
<div>
<button>Content</button>
</div>
{% endblock %}
{% block foot %}
<div>
<button>Foot</button>
</div>
{# 导入其他模板文件 #}
{% include 'child_include.html' %}
{% endblock %}
注意:子模版会默认覆盖父模板,如果想将内容继承过来,则需要使用 {``{ block.super }}
.
jinja2:
在Django项⽬中使⽤Jinja2模板引擎,Jinja2是之前我们在Flask框架讲过的⼀个模板引擎,是模仿Django默认模板引擎基础上开发的,⽐Django模板引 擎性能更好,功能更全.
jinja2宣称⽐django默认模板引擎快10-20倍。Django也⽀持jinja2
首先需要安装jinja2:
pip install jinja2 -i https://pypi.tuna.tsinghua.edu.cn/simple/
py
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': static,
'url': reverse,
})
return env
在setting.py做修改:
py
TEMPLATES = [
{
"BACKEND": 'django.template.backends.jinja2.Jinja2',
"DIRS": [BASE_DIR / 'templates'],
"APP_DIRS": True,
"OPTIONS": {
# 这⾥要添加environment,并指定到jinja2_env⽂件中的environment
'environment': 'demo2.jinja2_env.environment',
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
# 原来自带的Django模板引擎
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'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',
],
},
},
]
修改模板语言提示配置:
jinja2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>Jinja2模板语言</h2>
<hr>
<p>name: {{ name }}</p>
{% for n in name %}
<b>{{ n }}</b>
{% endfor %}
<hr>
{# 不能使用Django语法了 #}
{% for n in name %}
<div>{{ loop.index }}:{{ n }}</div>
{% endfor %}
<hr>
{# Jinja2 是可以使用函数调用 #}
{% for i in range(1, 4) %}
<div>{{ i }}</div>
{% endfor %}
</body>
</html>
注意:
在Flask中,传递参数使用关键词传递参数,而Django使用字典传参数。
py
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'index.html', {'name': 'zhangsan'})
总结:
通过本文的详细讲解,我们对Django模板的基础知识有了全面的了解。从如何在HTML中显示数据、使用循环和判断语句、应用过滤器等等,我们掌握了丰富的技巧和技能。同时,我们也学习了模板的继承与融合,为构建复杂而灵活的网页奠定了基础。
此外,我们还介绍了如何在Django中配置使用Jinja2语法,为开发者提供了更多的选择和灵感。通过灵活运用这些工具和技术,我们能够创建出更加强大、美观且可维护的Web应用程序。
希望本文能对读者在学习和使用Django模板时提供帮助。掌握了这些知识和技巧,相信你能够更加高效地开发出出色的Web应用。继续深入学习和实践,开拓更广阔的技术领域吧!