首页 > 技术文章 > django--第四章 模板系统

hoyun 2021-12-13 15:50 原文


前言

Django 的模板语言旨在在强大和易用之间取得平衡。它旨在让那些习惯于使用 HTML 的人感到舒适。如果您接触过其他基于文本的模板语言,例如SmartyJinja2,那么您应该对 Django 的模板感到宾至如归。

如果您有编程背景,或者如果您习惯于将编程代码直接混合到 HTML 中的语言,您需要牢记 Django 模板系统不仅仅是将 Python 嵌入到 HTML 中。这是设计使然:模板系统旨在表达表示,而不是程序逻辑。

Django 模板系统提供的标签功能与一些编程结构类似——if布尔测试for 标签、循环标签等——但这些不是简单地作为相应的 Python 代码执行,模板系统不会执行任意的 Python 表达式. 默认情况下仅支持下面列出的标签、过滤器和语法(尽管您可以根据需要向模板语言添加自己的扩展)。

推荐博客:https://www.cnblogs.com/wupeiqi/articles/5237704.html


模板

模板只是一个文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV 等)。
模板包含变量(在评估模板时用值替换)和标签(控制模板的逻辑)。
Django模板语言的语法主要分为2种:
​ {{变量}}:主要用于和视图变量做替换;
​ {% tag %}:主要用于做逻辑判断和实现某些功能,正因有了数据+逻辑才构成了模板语言;


应用中如果使用模板,则需要如下步骤:

  1. *添加模板路径:*修改settings.py配置,在TEMPLATES中修改DIRS。指定TEMPLATES的目录:
点击查看代码
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # 修改内容,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',
            ],
        },
    },

  1. 现在修改 appo1\views.py,增加一个新的对象,用于向模板提交数据:
点击查看代码
from django.shortcuts import render
def test(request):
    context = {'hello': 'Hello World!'}
    return render(request, 'moban.html', context)

  1. 在 templates 目录下创建 moban.html 文件,写入以下内容:
点击查看代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>模板练习</title>
</head>
<body>
    {% for v in context.values %}
    	<p>{{v}} </p> 
    {% endfor %}
</body>
</html>

  1. 在 urls.py 文件中加上url:
点击查看代码
from django.urls import path
from app01 import views

urlpatterns = [    path('test/', views.test),  ]

  1. 访问 http://127.0.0.1:8000/test,可以看到页面:



变量用法

当模板引擎遇到一个变量时,它会评估该变量并将其替换为结果。变量名称由字母数字字符和下划线 ( )的任意组合组成,但不能以下划线开头。点 ( ) 也出现在可变部分中,尽管它具有特殊含义,如下所示。重要的是,变量名中不能有空格或标点符号。{{ variable }}``"_"``"." 。使用点 ( .) 访问变量的属性。

从技术上讲,当模板系统遇到一个点时,它会按以下顺序尝试以下查找:

  • 字典查找
  • 属性或方法查找
  • 数字索引查找

如果结果值是可调用的,则不带参数调用它。调用的结果成为模板值。


  • 变量:字符串
点击查看代码
# app01/views.py
def moban(request):
    name = '变量'
    return render(request, 'moban.html', {'name': name})
点击查看代码
# templates/moban.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
</head>
<body>
    <h1> {{ name }} </h1> <!-- 变量使用方式 -->
</body>
</html>
点击查看代码
# urls.py
from django.urls import re_path
from app01 import views
urlpatterns = [re_path('moban/', views.moban),]

再次访问 http://127.0.0.1:8000/moban,可以看到页面:


  • 变量:列表

模板文件中,可以用 . 索引下标取出对应的元素。

点击查看代码
# app01/views.py
def moban(request):
    name = ['Python', 'Java', 'Go']
    return render(request, 'moban.html', {'name': name})
点击查看代码
# templates/moban.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
</head>
<body>
    <h3> {{ name }} </h3>    <!-- 取出整个列表 -->
    <h3> {{ name.0 }} </h3>  <!-- 取出列表的第一个元素  -->
    <h3> {{ name.2 }} </h3>  <!-- 取出列表的第三个元素  -->
</body>
</html>

再次访问 http://127.0.0.1:8000/moban,可以看到页面:


  • 变量:字典

模板文件中,可以用 .键 取出对应的值。

点击查看代码
# app01/views.py
def moban(request):
    name = { 'k1': 'kk1', 'k2': 'kk2',  'k3': 'kk3' }
    return render(request, 'moban.html', {'name': name})
点击查看代码
# templates/moban.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
</head>
<body>
    <h3> {{ name }} </h3>    <!-- 取出整个字典 -->
    <h3> {{ name.keys }} </h3>  <!-- 取出字典的 keys  -->
    {% for foo in name.values %}  <!-- 循环取出字典的每个值  -->
        <h3>{{ foo }}</h3>
    {% endfor %}
</body>
</html>

再次访问 http://127.0.0.1:8000/moban,可以看到页面:




标签用法

如果引用到了视图中的变量,还不足以渲染出一个完美的页面,那就要借助tag标签,做逻辑控制和功能完善了;

  • for 标签

语法: {% for %} {% endfor %}

点击查看代码
{% for foo in name.values %}  <!-- 循环取出字典的每个值  -->
<h3>{{ foo }}</h3>
{% endfor %}

  • if 标签

语法:{% if ... %} {% elif ... %} {% else %} {% endif %}

点击查看代码
# templates/moban.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
</head>
    {% if 'k1' in name.keys %}
        <P>'k1'</P>
    {% elif 'k2' in name.keys %}
        <p>'k2'</p>
    {% else %}
        <p>{{ name.keys }}</p>
    {% endif %}
</body>
</html>




过滤器用法

可以使用过滤器修改要显示的变量。Django 提供了大约 60 个内置模板过滤器。您可以在内置过滤器参考中阅读有关它们的所有信息。

语法:{{ 变量名 | 过滤器:可选参数 }}


  • lower
点击查看代码
{{ name|lower  }}
# 表示将变量name的值全部变成小写
# 竖线|可以理解为python中的圆点(.)

  • if 标签中使用
点击查看代码
# 可以在if标签中,使用过滤器,并结合运算符一起使用
{% if name|length > 2 %}

  • 串联方式
点击查看代码
# 过滤器可以用来串联,构成过滤器链
{{name | lower | upper}}

  • 默认值
点击查看代码
{{ value|default:"nothing" }}
# 如果变量为 false 或为空,则使用给定的默认值。否则,使用变量的值。




自定义simp-tag和filter

模板语言自带的tag和过滤器,在某些情况下还不能满足我的功能需求,例如无法实现递归显示需求等,可以自定义filtersimp-tag;就像Python内置函数和自定义函数关系;

filter语法:{{ 第一个参数 | 函数名称:第二个参数 }},最多支持二个参数。

simp-tag语法:{% 函数名称 "参数一" "参数二" "参数三" %}

1、在app中创建 templatetags目录或Python包(注意 该包的名称必须为 templatetags


2、templatetags文件夹下自定义创建个Python文件,例如:mytag.py;

点击查看代码
# app01/templatetags/mytag.py
from django import template     # 用于模板自定义函数的

register=template.Library() 

# 自定义函数
@register.filter    # filter最多支持两个参数
def my_filter(value, arg):  # value, arg 为前端传递的参数
    return value + arg

@register.simple_tag  #自定义tag 就使用 simlep_tag装饰器
def my_simple_tag(value):  # value为前端传递的参数
    return value.lower()

3、moban.html文件中应用自定义函数方法

点击查看代码
{% load mytag %}      <!--导入文件 注意: 顶部必须写,Django规则 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
</head>
<body>
    {% for foo in name.values %}    <!-- 循环取出字典的每个值  -->        
    	<h3>{{ foo  | my_filter:"第二个参数" }}</h3>  <!--加其他参数,注意冒号后不能加空格-->
    {% endfor %}
    
    <h3>{% my_simple_tag "ALEX" %}</h3>  <!-- simple_tag用法,支持多个参数,空格分隔字符串 -->
</body>
</home>

4、 在settings中配置当前app,不然django无法找到自定义的simple_tag:

点击查看代码
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',     # 注册APP应用




模板继承

模板可以用继承的方式来实现复用,减少冗余内容。

网页的头部和尾部内容一般都是一致的,我们就可以通过模板继承来实现复用。

父模板用于放置可重复利用的内容,子模板继承父模板的内容,并放置自己的内容。

  • 母模板

标签 block...endblock: 母模板中的预留区域,该区域留给子模板填充差异性的内容,不同预留区域名字不能相同。

{% block 名称 %} 
用于子版引用的区域,可以设置默认内容
{% endblock 名称 %}

  • 子模板

子模板使用标签 extends 继承母模板:

{% extends "被继承.html(母版)文件路径"%} 

子模板如果没有设置母模板预留区域的内容,则使用在母模板设置的默认内容,当然也可以都不设置,就为空。

子模板设置母模板预留区域的内容:

{ % block 名称 % }
中间加自定义的内容
{% endblock 名称 %}

  • 继承CSS

继承母版的CSS,子版自定义的内容将替换母版对应位置,自定义的内容只能子版生效

{% block css %} 中间加自定义的内容 {% endblock %}   

  • 继承JS

继承母版中 js 的内容,子版自定义的内容将替换母版对应位置,自定义的内容只能子版生效

{% block js %} 中间加自定义的内容  {% endblock %}

母版继承示例:

点击查看代码
# muban.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>母版继承练习</title>
</head>
<body>
    <h1>Hello World!</h1>
    <div>    <p>母版</p>
    	{% block mainbody %}	
       		<p>original</p>		<!-- 子模板继承范围 -->
    	{% endblock %}
    </div>
</body>
</html>

以上代码中,名为 mainbody 的 block 标签是可以被继承者们替换掉的部分。

所有的{% block %}标签告诉模板引擎,子模板可以重载这些部分。

ziban.html 中继承 muban.html 文件,并替换特定 block,ziban.html 修改后的代码如下:

点击查看代码
{%extends "muban.html" %}    <!-- 继承母版文件 -->
 
{% block mainbody %}
<p>继承了 muban.html 文件中指定位置</p>   <!-- 在母版中 block 位置需要显示的内容 -->
{% endblock %}

第一行代码说明 ziban.html 继承了 muban.html 文件。可以看到,这里相同名字的 block 标签用以替换 muban.html 的相应 block




include 标签

当我们在多个 HTML 模板中都需要用到用户自定义的 HTML 内容,我们可以尝试把这些每个页面都拥有的相同的内容单独抽离出来放在另外的html页面进行维护。

include标签主要实现的作用:{% include ‘子模板名称’ %} 标签允许在当前模板中包含其它的模板的内容。

<!--  include.html  -->
<div>
    <p>公共部分内容....   </p>
</div>
<!--  test.html  -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>导入include模板</title>
    </head>
    <body>
        {% include 'include.html' %}  # 导入include文件
    </body>
</html>

以上内容启动服务器后显示情况如下:




推荐阅读