前言
系列文章目录
[Python]目录
视频及资料和课件
链接:https://pan.baidu.com/s/1LCv_qyWslwB-MYw56fjbDg?pwd=1234
提取码:1234
1. 模板的配置
在项目中单独创建一个文件夹templates,用于存放模板。
设置模板的查找路径
'DIRS': [ os.path.join(BASE_DIR, 'template') ],
2. 定义模板
定义模板其实就是定义一个html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
</body>
</html>
3. 模板的使用
调用模板分为两步骤:
- 找到模板,模板文件在模板目录中的相对路径 -> 返回模板对象
- 渲染模板
渲染模板使用Django提供的函数render()
。
render(request对象, 模板文件路径, 模板数据字典)
from django.shortcuts import render
from django.http import HttpRequest
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import redirect
from django.urls import reverse
import json
from django.views import View
# Create your views here.
# 使用类视图
class LoginView(View):
# get用于处理页面资源的获取
def get(self, request):
# 假设姓名数据为 张三
name = '张三'
# 组织传递给模板的数据
# 将数据传递给模板,需要使用字典进行传递
context = {
'name': name
}
# render第一个参数为请求对象,第二个参数为模板路径,第三个参数为数据字典
# 对模板进行渲染,并返回渲染后的页面
return render(request, 'index.html', context)
def post(self, request):
return HttpResponse('post')
路由配置:
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', include(('login.urls', 'login'), namespace='login')),
path('book/', include(('book.urls', 'book'), namespace='book'))
]
from django.urls import path
from login import views
urlpatterns = [
path('', views.login),
path('set_cookie/', views.set_cookie),
path('get_cookie/', views.get_cookie),
path('del_cookie/', views.del_cookie),
path('set_session/', views.set_session),
path('get_session/', views.get_session),
path('class_login/', views.LoginView.as_view())
]
4. 模板语法
准备将要渲染到页面的数据:
class LoginView(View):
def get(self, request):
# 假设从数据库中查询出来的姓名为 张三
name = '张三'
# 将数据传递给模板,需要使用字典进行传递
context = {
'name': name,
'age': 24,
'birthday': datetime.now(),
'friends': ['tom', 'jack', 'rose'],
'money': {
'2019': 12000,
'2020': 15000,
'2021': 20000
}
}
# render第一个参数为请求对象,第二个参数为模板路径,第三个参数为数据字典
return render(request, 'index.html', context)
def post(self, request):
return HttpResponse('post')
4.1 模板变量
变量名必须由字母、数字、下划线(不能以下划线开头)和点组成。
模板变量的变量名要与传递进来的数据的变量名一致
语法如下:
{{ 模板变量 }}
模板变量可以使python的内建类型,也可以是对象。
4.2 获取指定的数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>生日:{{ birthday }}</p>
<p>朋友:{{ friends }}</p>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.2019 }}</p>
</body>
</html>
4.3 模板中的for循环
语法:
{% for item in items %}
循环体
{% endfor %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>生日:{{ birthday }}</p>
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ forloop.counter }} {{ forloop.counter0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.2019 }}</p>
</body>
</html>
4.4 if语句
语法:
注意:符号的两边要有空格
{% if age < 10 %}
...
{% elif age >= 10 and age < 20 %}
...
{% else %}
...
{% endif %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>
{% if age < 10 %}
年龄小于10
{% elif age >= 10 and age < 20 %}
年龄大于10小于20
{% else %}
年龄大于20
{% endif %}
</p>
<p>生日:{{ birthday }}</p>
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ forloop.counter }} {{ forloop.counter0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.2019 }}</p>
</body>
</html>
4.5 模板语法中的运算符
比较运算符如下:
==
!=
<
>
<=
>=
布尔运算符如下:
and
or
not
4.6 模板语法中的注释
1)单行注释语法如下:
{# 注释内容 #}
2)多行注释使用comment标签,语法如下:
{% comment %}
注释内容
{% endcomment %}
5. 过滤器
过滤器的本质为一个函数。
语法如下:
变量|过滤器:参数
- 使用管道符号
|
来应用过滤器,用于进行计算、转换操作,可以使用在变量、标签中。 - 如果过滤器需要参数,则使用冒号
:
传递参数。
常见的过滤器:
- safe,禁用转义,告诉模板这个变量是安全的,可以解释执行
- length,长度,返回字符串包含字符的个数,或列表、元组、字典的元素个数。
- default,默认值,如果变量不存在时则返回默认值。
- date,日期,用于对日期类型的值进行字符串格式化,常用的格式化字符如下:
- Y表示年,格式为4位,y表示两位的年。
- m表示月,格式为01,02,12等。
- d表示日, 格式为01,02等。
- j表示日,格式为1,2等。
- H表示时,24进制,h表示12进制的时。
- i表示分,为0-59。
- s表示秒,为0-59。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>
{% if age < 10 %}
年龄小于10
{% elif age >= 10 and age < 20 %}
年龄大于10小于20
{% else %}
年龄大于20
{% endif %}
</p>
<p>生日:{{ birthday|date:'Y-m-d H:i:s' }}</p>
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ forloop.counter }} {{ forloop.counter0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.2019 }}</p>
</body>
</html>
6. 模板继承
模板继承和类的继承含义是一样的,主要是为了提高代码重用,减轻开发人员的工作量。
父模板:
如果发现在多个模板中某些内容相同,那就应该把这段内容定义到父模板中。
标签block:
用于在父模板中预留区域,留给子模板填充差异性的内容,预留区域的名字不能相同。 为了更好的可读性,建议给endblock标签也写上名字,这个名字与对应的block名字相同。父模板中也可以使用传递过来的数据。
语法:
{% block 名称 %}
预留区域,可以编写默认内容,也可以不编写默认内容
{% endblock 名称 %}
子模板:
标签extends:继承,写在子模板文件的第一行。
语法:
{% extends "父模板路径" %}
填充父模板中指定名称的预留区域。
子模版不用填充父模版中的所有预留区域,如果子模版没有填充,则使用父模版定义的默认值。
{% block 名称 %}
重写预留区域
{% endblock 名称 %}
父模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
页面标题
{% endblock title %}
</title>
</head>
<body>
{% block header %}
<h1>页面的顶部</h1>
{% endblock header %}
{% block main %}
<h1>页面的主要部分</h1>
{% endblock main %}
{% block footer %}
<h1>页面的底部</h1>
{% endblock footer %}
</body>
</html>
继承父模板重写index.html:
{# 继承父模板 #}
{% extends "base.html" %}
{# 重写页面标题区域 #}
{% block title %}
张三的个人介绍
{% endblock title %}
{# 重写页面的主体区域 #}
{% block main %}
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>
{% if age < 10 %}
年龄小于10
{% elif age >= 10 and age < 20 %}
年龄大于10小于20
{% else %}
年龄大于20
{% endif %}
</p>
<p>生日:{{ birthday|date:'Y-m-d H:i:s' }}</p>
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ forloop.counter }} {{ forloop.counter0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.2019 }}</p>
{% endblock %}
{# 不需要底部区域,重写底部区域 #}
{% block footer %}{% endblock %}
7. jinja2模板
Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,尤其是Flask框架内置的模板语言。
7.1 安装jinja2模板
pip install jinja2
pip3 install jinjia2 -i https://pypi.tuna.tsinghua.edu.cn/simple
7.2 Django配置jinja2
在settings.py文件:
TEMPLATES = [
{
# 'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改为jinja2模板
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [ os.path.join(BASE_DIR, 'template') ],
'APP_DIRS': True,
'OPTIONS': {
# 默认的
# 'environment': 'jinja2.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',
],
},
},
]
报错的话,使用下面的配置设置:
ERRORS: ?: (admin.E403) A 'django.template.backends.django.DjangoTemplates' instance must be configured in TEMPLATES in order to use the admin application.
来源:08、jinja2模板使用
TEMPLATES = [
{
# 'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改为jinja2模板
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [ os.path.join(BASE_DIR, 'template') ],
'APP_DIRS': True,
'OPTIONS': {
# 设置jinja2的环境变量
# 默认设置就为这个,可以不用配置该项
# 'environment': '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',
],
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ os.path.join(BASE_DIR, 'template') ],
'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',
],
},
},
]
7.3 jinja2模板与Django自带模板的区别
jinja2模板没有多行注释
{% comment %} 注释内容 {% endcomment %}
jinja2模板中的过滤器使用的就是函数,不为
变量|过滤器:参数
,如:在Django自带的模板中date过滤器的写法为birthday|date:'Y-m-d H:i:s'
,在jinja2中直接写函数形式date(birthday)
jinja2中不存在forloop,使用的为loop,jinja2中的loop:
{# 继承父模板 #}
{% extends "base.html" %}
{# 重写页面标题区域 #}
{% block title %}
张三的个人介绍
{% endblock title %}
{# 重写页面的主体区域 #}
{% block main %}
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>
{% if age < 10 %}
年龄小于10
{% elif age >= 10 and age < 20 %}
年龄大于10小于20
{% else %}
年龄大于20
{% endif %}
</p>
{# <p>生日:{{ birthday|date:'Y-m-d H:i:s' }}</p>#}
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ loop.index }} {{ loop.index0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.first }}</p>
{% endblock %}
{# 不需要底部区域,重写底部区域 #}
{% block footer %}{% endblock %}
7.4 jinja2过滤器
在jinja2_env.py文件中设置jinja2的过滤器.
jinja2_env.py 定义在项目的文件夹目录下
from jinja2 import Environment
# 导入Django中模板的过滤器函数
from django.template.defaultfilters import date
def environment(**options):
# 创建Environment实例
env = Environment(**options)
# 指定jinja2的函数执行django的指定过滤器
env.globals.update({
'data': date
})
return env
修改配置jinja2的环境配置:
TEMPLATES = [
# jinja2模板配置
{
# 'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改为jinja2模板
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [ os.path.join(BASE_DIR, 'template') ],
'APP_DIRS': True,
'OPTIONS': {
# 设置jinja2的环境变量
# jinja2的默认环境
# 'environment': 'jinja2.Environment',
# 我们自己的jinja2环境
'environment': 'django_pro2.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': [ os.path.join(BASE_DIR, 'template') ],
'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过滤器:
{# 继承父模板 #}
{% extends "base.html" %}
{# 重写页面标题区域 #}
{% block title %}
张三的个人介绍
{% endblock title %}
{# 重写页面的主体区域 #}
{% block main %}
<h1>hello world</h1>
{# name 为模板等待接收的数据,需要View查询数据库传入模板 #}
<h1>你好 {{ name }}</h1>
<p>年龄:{{ age }}</p>
<p>
{% if age < 10 %}
年龄小于10
{% elif age >= 10 and age < 20 %}
年龄大于10小于20
{% else %}
年龄大于20
{% endif %}
</p>
{# 使用jinja2中的过滤器 #}
{# 第一个参数为需要进行过滤处理的数据,第二个参数为过滤器需要传递的参数 #}
<p>生日:{{ date(birthday, 'Y-m-d H:i:s') }}</p>
<p>朋友:</p>
<ul>
{# for 循环 #}
{% for friend in friends %}
{# forloop.counter 获取循环的次序,forloop.count0 获取下标 #}
<li>{{ loop.index }} {{ loop.index0 }} {{ friend }}</li>
{% endfor %}
</ul>
{# 获取列表中的某个元素,使用点+下标的方式进行获取 #}
<p>女朋友:{{ friends.2 }}</p>
{# 获取字典中的某个元素,使用点+key的形式获取 #}
<p>第一年的薪资:{{ money.first }}</p>
{% endblock %}
{# 不需要底部区域,重写底部区域 #}
{% block footer %}{% endblock %}
7.5 修改pycharm的模板引擎
7.6 自定义过滤器
在jinja2_env.py文件中自定义过滤器
from jinja2 import Environment
# 导入Django中模板的过滤器函数
from django.template.defaultfilters import date
def environment(**options):
# 创建Environment实例
env = Environment(**options)
# 指定jinja2的函数执行django的指定过滤器
env.globals.update({
'date': date,
# 将自定义的过滤器添加
'do_listreverse': do_listreverse
})
return env
# 1.自定义过滤器
def do_listreverse(li):
if li == "B":
return "哈哈"
{# 继承父模板 #}
{% extends "base.html" %}
{# 重写页面标题区域 #}
{% block title %}
张三的个人介绍
{% endblock title %}
{# 重写页面的主体区域 #}
{% block main %}
<h1>{{ do_listreverse('B') }}</h1>
{% endblock %}
{# 不需要底部区域,重写底部区域 #}
{% block footer %}{% endblock %}