Django 基础知识详细图文教程 10-Django 模板引擎 3

来源引用网络知识与某站曹老师视频相互结合学习记录,仅供参考!

Django 模板引擎

Django 作为 Web 框架,需要一种很便利的方法动态地生成 HTML 网页,因此有了模板这个概念;模板包含所需 HTML 的部分代码以及一些特殊语法,特殊语法用于描述如何将视图传递的数据动态插入 HTML 网页中;简单来说,模板引擎的具体思路就是通过一个通用模板加动态数据等于生成一个网页。

Django 可以配置一个或者多个模板引擎(甚至是 0 个,例如前后端分离(就不需要模板了,只需要提供 API 接口,返回 JSON 数据),Django 只提供 API 接口,无须使用模板引擎),模板引擎有Django 模板语言(Django Template Language,DTL)和 Jinja3;Django 模板语言是Django 内置的功能之一,Jinja3 是当前 Python 流行的模板语,Jinja3 是对Django 内置模板的一个扩展,一些高级开发扩展一般建议使用Jinja。

Django 内置模板引擎

Django 内置的模板引擎包含模板上下文 (亦可称为模板变量)、标签过滤器,各个功能说明如下:

  • 模板上下文是以变量的形式写入模板文件里面,变量值由视图函数或视图类传递所得;
  • 标签是对模板上下文进行控制输出,比如模板上下文的判断和循环控制等;
  • 公共模板抽取,模板继承隶属于标签,它是将每个模板文件重复的代码抽取出来并写在一个共用的模板文件中,其他模板文件通过继承共用模板文件来实现完整的网页输出;
  • 过滤器是对模板上下文进行操作处理;例如说模板上下文的内容截取、替换或者格式转化等。
模板上下文

模板上下文是模板中基本的组成单位,上下文的数据由视图函数或视图类传递;它是以两个大/花括号,里面加上变量内容来{{ variable }}表示,其中 variable 是上下文的名称,它支持 Python 所有的数据类型 ,如字典、列表、元组、字符串、整型或实例化对象等;上下文的数据格式不同,在模板里的使用方式也有所差异;

自定义标签

标签是对模板上下文进行控制输出,它是以{% tag %}表示的,其中 tag是标签的名称,Django内置了许多模板标签;例如:{% if %}(判断标签)、{% for %}(循环标签)或{% url %}(路由标签)等;

模板继承

Django模板继承是一个强大的工具,可以将通用页面元素(比如说"页眉、页脚、侧边栏"等)分离出来,并在多个页面之间共享它们;就是说可以做一个基础模板,其他页面的模板可以继承这个基础模板来实现一个通用功能的一些封装;模板继承和 Python 语言中类的继承含义是一样的,在 Django 中模板只是一个文本文件(例如:HTML),只需要一个文件(HTML)放在 templates 模板目录文件路径下即可;模板继承是 Django 模板语言中最强大的部分,模板继承可以构建基本的"骨架"模板,将通用的功能或者属性写在基础模板中,也叫基类模板或者父模板;子模板可以继承父类模板,子模板继承后将自动拥有父类中的属性和方法,还可以在子模板中对父模板进行重写,即重写父模板中方法或者属性,从而实现子模板的定制;模板继承大大提高了代码的可重用性,减轻开发人员的工作量;

在模板继承中最常用了标签就是 {% block %} 与 {% extends %} 标签,其中 {% block% } 标签与 {% endblock %} 标签成对出现;

自定义过滤器

Django过滤器是一种用于在Django模板中处理数据的一种技术;过滤器的作用是可以对模板中的变量进行加工、过滤或格式化,返回一个新的值供模板使用;过滤器作用是在变量输出时,对输出的变量值做进一步的处理,可以使用过滤器来更改变量的输出显示;过滤器跟模板标签一样,也是在模板中对函数进行调用对输出的日期进行格式化处理,或者转换大小写字母等,这些都是有对应的过滤器去处理它们;

过滤器的语法格式():

{{ 变量 | 过滤器1:参数值1 | 过滤器2:参数值2 ... }}

复制代码
{{ 变量 过滤器1:参数值1 | 过滤器2:参数值2 ... }}

● 首先是"模板变量"
● 其次是一个竖线"|(管道符)"
● 后面再跟"过滤器的名称"
● 然后冒号":"后面跟参数
里面可以跟多个管道过滤器,可以处理多次。

Jinja 模板引擎

Jinja是Python里面被广泛应用的模板引擎,目前最新版本3.1.6 版本,所以有部分人称为Jinja3,但是Jinja2 版本使用时间长,且是长期维护的,也被很多人叫"Jinja2",至于为什么不叫"Jinja3"版本呢?是因为目前安装时使用的还是"Jinja2"的方式,安装的也是最新 v3.1.6 版本,但是Jinja 官方社区并没有宣称"Jinja3"版本,到目前为止仍是声称为"Jinja2 Version 3.1.6"版本,虽然说挺奇怪的,不过并不妨碍学习使用;它的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,所以它是Django模板引擎的扩展,因此功能更加的丰富、强大,如果是需要一些强大功能的时候,建议可以使用Jinja3 模板引擎,一般情况下在开发过程中使用内置的Django模板引擎就够了;

Jinja3 模板引擎其中最显著的是增加了沙箱执行功能和可选的自动转义功能,这对大多数应用的安全性来说是非常重要,如果是安全性要求很高的项目,可以使用Jinja3 模板引擎;此外,它还具备以下特性:

  • 沙箱执行模式,模板的每个部分都在引擎的监督之下执行,模板将会被明确地标记在白名单或黑名单内,这样对于那些不信任的模板也可以执行;
  • 安全性,强大的自动HTML转义系统,可以有效地阻止跨站脚本攻击;
  • 模板继承机制,此机制可以使得所有模板具有相似一致的布局,也方便开发人员对模板进行修改和管理。;
  • 高效的执行效率,Jinja3 模板引擎的执行效率会高一些,Jinja3引擎在模板第一次加载时就把源码转换成Python字节码,加快模板执行时间;
  • 调试系统融合了标准的Python的TrackBack功能,使得模板编译和运行期间的错误能及时被发现和调试;
  • 语法配置,可以重新配置Jinja3,使得它更好地适应开发(LaTeX或JavaScript 的输出);
    官方文档手册,此手册指导设计人员更好地使用Jinja3引擎的各种方法; Django支持 Jinja3模板引擎的使用,由于Jinja3的设计思想来源于Django 的模板引擎,因此Jinja3的使用方法与 Django 的模板语法有相似之处。

GitHub 开源主页:GitHub - pallets/jinja: A very fast and expressive template engine. · GitHub

官方文档:https://jinja.palletsprojects.com/en/stable/

安装和配置
安装

烦请自行选择安装方式;

pip命令安装;

复制代码
pip install Jinja2 -i https://pypi.tuna.tsinghua.edu.cn/simple

Python 解释器安装;

  1. 打开PyCharm 工具,鼠标光标滑动到菜单栏"文件(F)"选项,在文件下拉选择菜单中选中"设置(T)..."选项后单击打开设置对话框;
  2. 然后选择项目→Python 解释器→鼠标单击"➕"安装按钮,打开可用软件包对话框;
  3. 搜索框输入需要安装的第三方库(例如:Jinja);
  4. 选中"Jinja2"选项,自行选择是否指定安装版本,单击"安装软件包(I)"开始安装;

安装成功后自行查看;

Jinja3安装成功后,接着在 Django里配置Jinja3模板,由于 Django的内置功能是使用 Django的模板引擎,如果将整个项目都改为Jinja3模板引擎,就会导致内置功能无法正常使用,在这种情况下,既要保证内置功能能够正常使用,又要使用Jinja3模板引擎,只能将两个模板引擎共存在同一个项目里;

配置

在"djangoProject"应用下"settings.py"文件中有个"TEMPLATES"配置,可以配置多个TEMPLATES,它是一个数组、元组,所以说可以配置多个;里面默认会有一个"DjangoTemplates",可自定义配置其他项;例如:配置一个Jinja 的 Templates;

36、在"djangoProject"项目"helloWorld"应用下新建一个名称为"Jinja3 "的 Python 文件,用来定义环境参数;在其他地方新建也行,主要是一个配置,如果说一个项目里面只有一个子项目时,可直接在子项目中新建就行了;方式方法比较多,烦请自行选择;在"helloWorld"应用下"Jinja3.py"文件中输入以下内容(固定写法,自行设置);

复制代码
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment


def environment(**options):
    env = Environment(**options)
    env.globals.update(
        {
            # 读取项目类的静态资源配置
            'static': staticfiles_storage.url,
            # url反转
            'url': reverse
        }
    )
    # 返回一个env = Environment(**options)对象
    return env

37、修改"djangoProject"应用下"settings.py"文件中"TEMPLATES"配置项,添加配置一个Jinja 的 templates(固定配置内容,自行设置);

  • 'BACKEND': 'django.template.backends.jinja2.Jinja2'--固定写法,不用更改;
  • 'DIRS': BASE_DIR / 'templates'--指定模板路径,自行配置一个或多个;
  • 'APP_DIRS': True--表示在子项目下找不到的话就去找父项目;一般情况下都是配置为True;
  • 'OPTIONS': {'environment': 'helloWorld.Jinja3.environment'}--一些环境的配置,自行设置;
复制代码
"""
Django settings for djangoProject project.

Generated by 'django-admin startproject' using Django 5.0.6.

For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-i01#=6cjknb()(5@p19olv+c2$tf7ez86)r%g!b&5(2&pdkfd0'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "helloWorld.apps.HelloworldConfig",
    "user.apps.UserConfig",
    "order.apps.OrderConfig"
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'helloWorld.mymid.md1.Md1'
]

ROOT_URLCONF = 'djangoProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [BASE_DIR / 'templates']
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'environment': 'helloWorld.Jinja3.environment'
        },
    },
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'helloWorld/templates', 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',
            ],
        },
    },
]

WSGI_APPLICATION = 'djangoProject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_django6',
        'USER': 'root',
        'PASSWORD': '123',
        'HOST': '192.168.88.145',
        'PORT': '3306'
    }
}


# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/

STATIC_URL = 'static/'

# 设置静态资源文件集合
STATICFILES_DIRS = [BASE_DIR / "static", BASE_DIR / "helloWorld/images", BASE_DIR / "common"]

# 设置媒体路由
MEDIA_URL = 'media/'
# 设置media目录的完整路径
MEDIA_ROOT = BASE_DIR / 'media'

# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

配置完成之后,"JinjaTemplates"的优先级在"DjangoTemplates"之前,现在是"DjangoTemplates"和"JinjaTemplates"两个模板引擎共存的;

Django 里面还内置了一些"Auth(django.contrib.auth)、Admin(django.contrib.admin) 后台管理系统"等功能,默认使用的是Django模板引擎,如若把"DjangoTemplates"去掉之后,这些就不能用了;当然,在实际项目开发过程中是不使用这些内置功能的,所以不使用的话就是可以去掉的,一般开发会自己开发出对应的一套 admin 或 auth 系统;因为可以自行开发,然后单独使用Jinja 模板引擎,反正就是掌握了之后,怎么使用都行。

测试验证

38、此时重新运行项目,浏览器输入"http://127.0.0.1:8000/index/"测试,可以发现打开的是项目"templates"目录文件下的"index.html"文件,因为优先查找的是父项目而不是"helloWorld"子项目;

39、修改项目"templates"目录文件下的"index.html"文件内容;

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title Is Django or Jinja Hello World</title>
</head>
<body>
    字典类型(Django模板引擎支持的' msg2.Jack ',Jinja模板引擎也支持):{{ msg2.Jack }}<br>
    字典类型(Django模板引擎不支持的' msg2['King'] ',Jinja模板引擎还支持):{{ msg2['King'] }}<br>
    <h1>定义一个h1大标题</h1>
    <p>定义一个段落</p>
    <a href="https://www.runoob.com/django/django-tutorial.html">这是一个"Django 教程"链接</a><br>
    <a href="https://jinja.palletsprojects.com/en/stable/">这是一个"Jinja 官方文档"链接</a><br>
<h2>h2标题 Django Hello World</h2>
    <p>又是一个段落;然后下面是一张图片。</p>
    <img src="https://www.runoob.com/wp-content/uploads/2015/01/admin1.png" width="280" height="200"  alt=""/>
    <br>
<a href="https://www.runoob.com/html/html-tutorial.html">这是一个"HTML 教程"链接</a>
</body>
</html>

40、浏览器输入"http://127.0.0.1:8000/index/"打开 index(重新打开或者刷新)页面测试查看,经测试验证,已经成功应用Jinja模板引擎;

模板语法

尽管Jinja3的设计思想来源于Django 的模板引擎,但在功能和使用细节上是有区别的,Jinja3比Django的模板引擎更加完善,在 Django 的基础上多做了一些扩展;而且Jinja3的模板语法在使用上与 Django的模板引擎存在一定的差异;具体区别可参考官方文档(Jinja3模板帮助手册):Template Designer Documentation --- Jinja Documentation (3.1.x);因此仅简单讲述Jinja3与 Django模板语言的语法使用区别;

41、复制"helloWorld"子项目"templates"目录文件下的"index.html"文件,复制替换掉项目"templates"目录文件下的"index.html"文件,需要注意是替换,既是两个"index.html"文件内容完全相同;

42、浏览器输入"http://127.0.0.1:8000/index/"打开 index(重新打开或者刷新)页面测试查看;

可以看到提示报错信息,暂时先修改这三个问题;

  1. 首先是 url,使用方法不对,是有区别,先注释掉 url 信息或者更改为 Jinja3 支持的方式;
  2. 其次是内置过滤器中的日期 date 数据信息指定格式化报错,暂时先删除整段内置过滤器内容;
  3. 然后是"forloop未定义",因为 Jinja 里面的 for 标签用法是不一样的,把 for 标签里面的三个"forloop"替换为"loop";

43、修改项目"templates"目录文件下的"index.html"文件内容,修改为 Jinja 支持的语法格式,输入以下内容;

复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title Is Django Hello World index2</title>
  </head>
  <body>
    模板取值--字符串:{{ content_msg }}<br>
    模板取值--字典类型:{{ msg2.Jack }},{{ msg2.Queen }},{{ msg2.King }},{{ msg2.King2 }}<br>
    模板取值--对象:{{ msg3.name }},{{ msg3.age }}<br>
    模板取值--列表:{{ msg4.0 }},{{ msg4.1 }},{{ msg4.2 }},{{ msg4.3 }},{{ msg4.4 }},{{ msg4.5 }},{{ msg4.6 }},{{ msg4.61 }}<br>
    模板取值--元组:{{ msg5.0 }},{{ msg5.6 }},{{ msg5.5 }},{{ msg5.4 }},{{ msg5.3 }},{{ msg5.2 }},{{ msg5.1 }},{{ msg5.11 }}<br>
    <h3>模板标签</h3>
    <p>遍历for标签:</p>
    {% for item in msg4 %}
        <p>这个是第{{ loop.counter }}次遍历</p>
        {% if loop.first %}
            <p>这个是第一项:{{ item }}</p>
        {% elif loop.last %}
            <p>这个是最后一项:{{ item }}</p>
        {% endif %}
    {% endfor %}
    <p>判断标签if</p>
    {% if content_msg == '模板变量' %}
        <p>模板变量</p>
    {% elif content_msg == '传递字符串类型--模板引擎' %}
        <p>传递字符串类型--模板引擎</p>
    {% else %}
        <p>其他</p>
    {% endif %}
    <p>url标签</p>
{#    <a href="{% url 'index' %}" target="_blank">请求index地址</a>#}
    <a href="{{ url('index') }}" target="_blank">请求index地址</a>
    <p>with标签</p>
    {% with info=content_msg %}
        {{ info }}
    {% endwith %}
    
    <h1>定义一个h1大标题"index2"</h1>
    <p>定义一个段落"index2"</p>
    <h2>h2标题"index2" Django Hello World</h2>
    <p>又是一个段落;"index2"然后下面是一张图片。</p>
    <img src="https://www.runoob.com/wp-content/uploads/2015/01/admin1.png" width="304" height="228"  alt=""/>
    <br>
    <a href="https://www.runoob.com/html/html-tutorial.html">这是一个"HTML 教程 index2"链接</a>
  </body>
</html>

44、浏览器输入"http://127.0.0.1:8000/index/"测试验证,又发现了不一样的缺陷,假如说对象的属性不存在时,某个属性不存在时 Django 的默认处理方式是空字符串,但不是 Jinja 的处理方式,在 Jinja 里面是会报错显示的;因为在 Jinja 里面是没有"counter"属性的,在 Jinja 里面是叫做"length"属性;

在for循环块内部,您可以访问一些特殊变量:Template Designer Documentation --- Jinja Documentation (3.1.x)

|---------------------|---|---|
| 变量(Variable) | 描述(Description)说明 ||
| loop.index | 循环的当前迭代(索引从 1 开始)。 ||
| loop.index0 | 循环的当前迭代(索引从 0 开始)。 ||
| loop.revindex | 循环结束后的迭代次数(索引从 1 开始)。 ||
| loop.revindex0 | 循环结束后的迭代次数(索引从 0 开始)。 ||
| loop.first | 如果是第一次迭代,就为True。 ||
| loop.last | 如果是最后一次迭代,则为True。 ||
| loop.length | 序列中的项目数,即循环总次数。 ||
| loop.cycle | 循环:一个在序列列表之间循环的辅助函数。辅助函数,用于在序列列表之间循环。 在for循环中,可以使用特殊的loop.cycle助手在每次循环中在字符串/变量列表之间循环。 自Jinja 2.1以来,存在一个额外的循环辅助器,允许循环无约束循环。有关更多信息,请查看全局函数列表。 ||
| loop.depth | 环路深度:指示渲染当前在递归循环中的深度,从级别1开始。 ||
| loop.depth0 | 指示渲染当前在递归循环中的深度,从级别0开始。 ||
| loop.previtem | 循环.审查:上一次迭代中的对象;循环前一次迭代中的项目,在第一次迭代中未定义。 ||
| loop.nextitem | 下一次迭代中的对象;循环后续迭代中的项目。在上次迭代中未定义。 ||
| loop.changed(*val) | 循环已更改(*val):如果之前用不同的值调用(或根本不调用),则为True。 若上传迭代的值与当前迭代的值不同,则返回True。 ||

45、继续修改项目"templates"目录文件下的"index.html"文件内容,修改为 Jinja 支持的语法格式,更改"counter"为"length"属性;

复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title Is Django Hello World index2</title>
  </head>
  <body>
    模板取值--字符串:{{ content_msg }}<br>
    模板取值--字典类型:{{ msg2.Jack }},{{ msg2.Queen }},{{ msg2.King }}<br>
    模板取值--对象:{{ msg3.name }},{{ msg3.age }}<br>
    模板取值--列表:{{ msg4.0 }},{{ msg4.1 }},{{ msg4.2 }},{{ msg4.3 }},{{ msg4.4 }},{{ msg4.5 }},{{ msg4.6 }},{{ msg4.61 }}<br>
    模板取值--元组:{{ msg5.0 }},{{ msg5.6 }},{{ msg5.5 }},{{ msg5.4 }},{{ msg5.3 }},{{ msg5.2 }},{{ msg5.1 }},{{ msg5.11 }}<br>
    <h3>模板标签</h3>
    <p>遍历for标签:</p>
    {% for item in msg4 %}
        <p>这个是第{{ loop.length }}次遍历</p>
        {% if loop.first %}
            <p>这个是第一项:{{ item }}</p>
        {% elif loop.last %}
            <p>这个是最后一项:{{ item }}</p>
        {% endif %}
    {% endfor %}
    <p>判断标签if</p>
    {% if content_msg == '模板变量' %}
        <p>模板变量</p>
    {% elif content_msg == '传递字符串类型--模板引擎' %}
        <p>传递字符串类型--模板引擎</p>
    {% else %}
        <p>其他</p>
    {% endif %}
    <p>url标签</p>
{#    <a href="{% url 'index' %}" target="_blank">请求index地址</a>#}
    <a href="{{ url('index') }}" target="_blank">请求index地址</a>
    <p>with标签</p>
    {% with info=content_msg %}
        {{ info }}
    {% endwith %}
    
    <h1>定义一个h1大标题"index2"</h1>
    <p>定义一个段落"index2"</p>
    <h2>h2标题"index2" Django Hello World</h2>
    <p>又是一个段落;"index2"然后下面是一张图片。</p>
    <img src="https://www.runoob.com/wp-content/uploads/2015/01/admin1.png" width="304" height="228"  alt=""/>
    <br>
    <a href="https://www.runoob.com/html/html-tutorial.html">这是一个"HTML 教程 index2"链接</a>
  </body>
</html>

46、浏览器输入"http://127.0.0.1:8000/index/"测试验证,可以看到已解决 for 标签中的"no such element"报错信息;

47、把"helloWorld"子项目"templates"目录文件下的"base.html"和"course.html"文件,复制一份到项目的"templates"目录文件路径下;

48、浏览器输入"http://127.0.0.1:8000/toCourse/"测试验证,可以看到还是会有报错信息,虽然Django 和 Jinja3在模板继承用法方面基本是一样的,但是在static函数用法上是有区别的,和 url 函数用法一样,也是不一样的;

49、修改项目"templates"目录文件路径下的"base.html"文件内容;

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
            Python 学习
        {% endblock %}
    </title>
</head>
{#先注释load static#}
{#{% load static %}#}
<body>
<div id="head">
{#    <img src="{% static 'Djangologo.png' %}">#}
{#    直接修改#}
    <img src="{{ static('Djangologo.png') }}">
</div>
<div id="content">
    {% block content %}
    这是 content 内容,它是一个子页面,基本都需要更改的,烦请自定义;
    {% endblock %}
</div>
<div id="footer">
    页脚footer约定好不需要修改,让所有的子类模板都能继承。
</div>
</body>
</html>

50、浏览器输入"http://127.0.0.1:8000/toCourse/"测试验证,能够正确打开展示相关页面;

总结:
  • url函数用法不一样;
  • 在遍历for标签上,属性不一样,Jinja3内置的对象是loop;
  • 如是是对象的属性不存在,或者是列表、元组的下标以及字典类型的元素,没有取到值时,Jinja3 都会返回具体的报错信息:no such element;
  • 相比较Django,Jinja3在static函数用法上也有区别,和 url 函数用法一样,也是不一样的;Django 和 Jinja3在模板继承方式是一样的;

主要就是这些区别,这些都需要掌握,要会看,其他某些情况可以查看具体文档。

过滤器

Jinja3的过滤器用法与 Django内置过滤器的使用方法基本上是一样的,有相似之处,也是由管道符号"|"连接模板上下文和过滤器,但是两者的过滤器名称是不同的,内置的过滤器种类是不一样的,而且过滤器的参数设置方式也不同;
具体使用可以参考下Jinja3官方文档Template Designer Documentation --- Jinja Documentation (3.1.x)

官方文档专门罗列出所有的 Jinja 过滤器,其中 Jinja3 常用过滤器如下所示;

|-----------|---|---|
| 过滤器 | 说明描述 ||
| abs | 设置数值的绝对值。 ||
| default | 设置默认值。 ||
| escape | 转义字符,转成HTML的语法。 ||
| first | 获取上下文的第一个元素。 ||
| last | 获取上下文的最后一个元素。 ||
| length | 获取上下文的长度。 ||
| join | 功能与Python的join语法一致。 ||
| safe | 将上下文转义处理。 ||
| int | 将上下文转换为int类型。 ||
| float | 将上下文转换为float类型。 ||
| lower | 将字符串转换为小写。 ||
| upper | 将字符串转换为大写。 ||
| replace | 字符串的替换。 ||
| truncate | 字符串的截断。 ||
| striptags | 删除字符串中所有的HTML标签。 ||
| trim | 截取字符串前面和后面的空白字符。 ||
| string | 将上下文转换成字符串。 ||
| wordcount | 计算长字符串的单词个数。 ||

51、修改项目"templates"目录文件路径下的"index.html"文件内容,添加 Jinja 过滤器实例;

复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title Is Django Hello World index2</title>
  </head>
  <body>
    模板取值--字符串:{{ content_msg }}<br>
    模板取值--字典类型:{{ msg2.Jack }},{{ msg2.Queen }},{{ msg2.King }}<br>
    模板取值--对象:{{ msg3.name }},{{ msg3.age }}<br>
    模板取值--列表:{{ msg4.0 }},{{ msg4.1 }},{{ msg4.2 }},{{ msg4.3 }},{{ msg4.4 }},{{ msg4.5 }},{{ msg4.6 }},{{ msg4.61 }}<br>
    模板取值--元组:{{ msg5.0 }},{{ msg5.6 }},{{ msg5.5 }},{{ msg5.4 }},{{ msg5.3 }},{{ msg5.2 }},{{ msg5.1 }},{{ msg5.11 }}<br>
    <h3>模板标签</h3>
    <p>遍历for标签:</p>
    {% for item in msg4 %}
        <p>这个是第{{ loop.length }}次遍历</p>
        {% if loop.first %}
            <p>这个是第一项:{{ item }}</p>
        {% elif loop.last %}
            <p>这个是最后一项:{{ item }}</p>
        {% endif %}
    {% endfor %}
    <p>判断标签if</p>
    {% if content_msg == '模板变量' %}
        <p>模板变量</p>
    {% elif content_msg == '传递字符串类型--模板引擎' %}
        <p>传递字符串类型--模板引擎</p>
    {% else %}
        <p>其他</p>
    {% endif %}
    <p>url标签</p>
{#    <a href="{% url 'index' %}" target="_blank">请求index地址</a>#}
    <a href="{{ url('index') }}" target="_blank">请求index地址</a>
    <p>with标签</p>
    {% with info=content_msg %}
        {{ info }}
    {% endwith %}
    
    <p>Jinja过滤器</p>
    first(获取第一个元素):{{ content_msg | first }}<br>
    last(获取最后一个元素):{{ content_msg | last }}<br>
    length(获取总长度):{{ content_msg | length }}<br>
    upper(将字符串转换为大写):{{ content_msg | upper }}<br>
    
    <h1>定义一个h1大标题"index2"</h1>
    <p>定义一个段落"index2"</p>
    <h2>h2标题"index2" Django Hello World</h2>
    <p>又是一个段落;"index2"然后下面是一张图片。</p>
    <img src="https://www.runoob.com/wp-content/uploads/2015/01/admin1.png" width="304" height="228"  alt=""/>
    <br>
    <a href="https://www.runoob.com/html/html-tutorial.html">这是一个"HTML 教程 index2"链接</a>
  </body>
</html>

52、浏览器输入"http://127.0.0.1:8000/index/"测试验证 Jinja 过滤器,均能够成功获取到对应的值。

未完待续......

相关推荐
拖孩41 分钟前
给小程序加「一键发公众号贴图」,我把 wx.shareToOfficialAccount 的三个坑趟了一遍
前端·后端·微信小程序
quantdash_cc43 分钟前
量化策略为什么需要实时行情数据?从信号产生到交易决策的时间差说起
开发语言·python·数据分析·量化交易·股票数据·quantdash
H Journey1 小时前
pip 和uv 开发和部署python项目
python·pip·uv
外收内放1 小时前
Python与AI应用(json模块)
python·学习
MetaLite1 小时前
全网最好的SpringBoot接口请求对象设计
java·spring boot·后端
蜗牛互联网1 小时前
AI给面试打分不够,求职者更需要可核对的证据
java·人工智能·后端
databook1 小时前
泊松分布:从基础到实际应用
python·数据挖掘·数据分析
EatFan1 小时前
gRPC 为什么比 HTTP+JSON 快?详细讲解gRPC
后端·微服务·grpc
外收内放1 小时前
Python与AI应用(文件操作)
python·学习