在django中,模板引擎(DTL)是一种可以让开发者将服务端数据填充到html页面中的完成渲染的技术

模板引擎的原理分为以下三步:

  • 在项目配置文件中指定保存模板文件的的模板目录,一般设置在项目根目录或者子应用目录下

  • 在模板目录下创建对应的模板文件

  • 在视图函数中通过render函数绑定模板文件和需要渲染的数据

1.模板目录

在简单的项目中,我们通常在项目的根目录下创建名为templates的文件夹,并在配置文件中设置模板目录

TEMPLATES = [
    {
        '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',
            ],
        },
    },
]

如果是多app的情况下,我们不仅要设置主模板目录,还要在每个app下创建对应的templates,包含该子app所需要的模板文件

TEMPLATES = [
    {
        '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',
            ],
        },
    },
]

 

 

 

提示:在使用模板的时候,django会到主模板目录下寻找,找不到会按照顺序到已注册的项目下的模板目录中寻找

简单案例

路由

from django.contrib import admin
from django.urls import path, include
from apps.app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/',views.index)
]

视图

def index(request):
    return render(request, 'app01/index.html')

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

 

2.render函数的本质

render函数的本质就是将模板文件中的所有变量替换成后端数据,生成一个html页面,也就是纯文本,响应给客户端

模板文件 & html页面的区别

模板文件是含有特殊语法的html文件,这个语法可以被django的DTL编译,将数据传进,实现动态话,渲染之后的模板文件也就是一个普通的html文件了

开发中我们常将普通的html称之为静态文件,将模板文件称之为动态文件

视图函数

def index(request):
    name = 'kunmzhao'
    return render(request, 'app01/index.html', {'name':name}) # 将数据传递给模板文件

模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>{{ name }}</p>  #含有模板语法
</body>
</html>

渲染之后的html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>kunmzhao</p> # 渲染之后
</body>
</html>

 

3.模板语法

3.1 句点符

变量渲染可以将对象原封不动的渲染在页面

 def index(request):
    # 字符串
    name = 'kunmzhao'
    # 数字
    age = 18
    # 列表
    course = ['语文', '数学', '英语']
    # 元组
    hobby = ('篮球', '足球')
    # 字典
    parents = {'father': 'mayun', 'mother': "dongmingzhu"}
    # 集合
    teachers = {'alex', 'victor'}

    return render(request, 'app01/index.html', {
        'name': name,
        'age': age,
        'course': course,
        'hobby': hobby,
        'parents': parents,
        'teachers': teachers,
    }

 

 

 句点符就可以访问对象中的属性

from django.shortcuts import render, HttpResponse


# Create your views here.
class Animal(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


def index(request):
    # 字符串
    name = 'kunmzhao'
    # 数字
    age = 18
    # 列表
    course = ['语文', '数学', '英语']
    # 字典
    parents = {'father': 'mayun', 'mother': "dongmingzhu"}

    # 对象
    dog = Animal('rubby', 3)

    return render(request, 'app01/index.html', {
        'name': name,
        'age': age,
        'course': course,
        'parents': parents,
        'dog': dog
    }
                  )
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ course.0 }}</p>  # 访问列表第几个元素
<p>{{ course.1 }}</p>
<p>{{ course.2 }}</p>
<p>{{ parents.father}}</p>  # 访问字典中键对应的值
<p>{{ parents.mother }}</p>
<p>{{ dog.name }}</p>  # 访问对象发的属性
<p>{{ dog.age }}</p>


</body>
</html>

 

3.2 过滤器

3.2.1 内置过滤器

内置过滤器最多有一个参数

语法:

{{obj|过滤器名称:过滤器参数}}
过滤器用法代码
last 获取列表/元组的最后一个成员 {{liast | last}}
first 获取列表/元组的第一个成员 {{list|first}}
length 获取数据的长度 {{list | length}}
defualt 当变量没有值的情况下, 系统输出默认值, {{str|default="默认值"}}
safe 让系统不要对内容中的html代码进行实体转义 {{htmlcontent| safe}}
upper 字母转换成大写 {{str | upper}}
lower 字母转换成小写 {{str | lower}}
title 每个单词首字母转换成大写 {{str | title}}
date 日期时间格式转换 {{ value| date:"D d M Y" }}
cut 从内容中截取掉同样字符的内容 {{content | cut:"hello"}}
list 把内容转换成列表格式 {{content | list}}
add 加法 {{num| add}}
filesizeformat 把文件大小的数值转换成单位表示 {{filesize | filesizeformat}}
join 按指定字符拼接内容 {{list| join("-")}}
random 随机提取某个成员 {list | random}}
slice 按切片提取成员 {{list | slice:":-2"}}
truncatechars 按字符长度截取内容 {{content | truncatechars:30}}
truncatewords 按单词长度截取内容 同上
def index(request):
    name = 'kunmzhao'
    hobby = ['篮球', '足球']

    return render(request, 'app01/index.html', {
        'name': name,
        'hobby': hobby,
    }
          )
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>{{ name|upper }}</p>
<p>{{ hobby|first }}</p>
<p>{{ hobby|last }}</p>
</body>
</html>

 

3.2.2 自定义过滤器

内置的过滤器可能没办法满足开发需求,django中支持使用自定义的过滤器

  • 确保定义过滤器所在的app已经注册

  • 在注册的app下创建templatetags的模块包

 

 

 

  • 创建py文件

  • 在文件中自定义过滤器

    from django import template
    
    register = template.Library()
    
    # 自定义过滤器
    @register.filter()
    def mobile(content):
        return content[:3] + "*****" + content[-3:]

     

  • 在模板中load过滤器并使用
    {% load my_filter %}  # 导入自定义的过滤器
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p>{{ phone|mobile }}</p>  # 使用过滤器
    </body>
    </html>

     

3.3 标签渲染

3.3.1 if

语法:

{% if 条件 %}
{%endif %}

视图

def index(request):
    score = 80
    return render(request, 'app01/index.html', {
        'score': score,
    }
 )

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if score > 90 %}
    <p>成绩优秀啊</p>
{% elif score > 80 %}
    <p>成绩良好</p>
{% else %}
    <p>成绩一般</p>
{% endif %}
</body>
</html>

 

 

 

3.3.2 for

语法

{% for i in iter %}
{%endfor %}

for标签中常用的方法

forloop.counter  : 从1开始每次循环自增1
forloop.counter0 : 从0开始每次循环自增1
forloop.first    : 是否是第一次循环
forloop.last    :  是否是最后一循环

视图

def index(request):
    hobby = ['篮球', '足球', '乒乓球']
    return render(request, 'app01/index.html', {
        'hobby': hobby,
    }
 )

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% for foo in hobby %}

    <p><span>{{ forloop.counter }}</span>{{ foo }}</p>
{% endfor %}

</body>

 

 

 

4.模板自定义

  • filter
    见自定义过滤器
    参数:1-2个
  • Simple_tag
    返回文本
    参数:无限制
  • Inclusion_tag
    返回html片段
    参数无限制

定义

# encoding:utf-8
# author:kunmzhao
# email:1102669474@qq.com
from django import template

register = template.Library()


# 自定义过滤器
@register.filter()
def mobile(content):
    return content[:3] + "*****" + content[-3:]


# 自定义simple_tag
@register.simple_tag()
def mytag(a1, a2):
    return a1 + a2


# 自定义inclusion_tag
@register.inclusion_tag("app01/menu.html")
def my_inclusion():
    return {'name': 'kunmzhao', 'age': 18}

模板

{% load my_filter %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>{{ phone |mobile }}</p>  # 使用自定义的过滤器
<p>{% mytag 100 200 %}</p>  # 使用自定义的tag函数
<p>{% my_inclusion %}</p>   # 使用自定义的inclusion_tag

</body>
</html>

menu.html

<p>
    <span>name={{ name }}</span>
    <span>age={{ age }}</span>
</p>

 

5.模板继承和导入

{% include "模板文件名"%}  # 模板嵌入
{% extends "base.html" %} # 模板继承

5.1 继承

语法
{%entends 模板文件%}  # 继承指定的模板文件

{% block 名称 %}  # 填充模板中的某一个block
    
{% endblock %}

视图

def index(request):
    return render(request, 'app01/header.html')

模板header.html

{% extends 'app01/index.html' %}
{% block  body%}
    <div>不畏浮云遮望眼,只缘身在最高层</div>
{% endblock %}

模板index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% block css %}
        {#   css样式  #}
    {% endblock %}
</head>
<body>
{% block body %}
    {# 内容填充 #}
{% endblock %}
</body>
</html>

 

 

 

5.2 导入

    {% include 片段文件名%}

视图

def index(request):
    return render(request, 'app01/header.html', {'name': 'kunmzhao', 'age': 18})

模板menu.html

<p>
    <span>name={{ name }}</span>
    <span>age={{ age }}</span>
</p>

模板header.html

{% extends 'app01/index.html' %}
{% block  body %}
    <div>不畏浮云遮望眼,只缘身在最高层</div>
    {% include 'app01/menu.html' %}  # 导入片段
{% endblock %}

 

 

 

6.静态文件

我们通常会将前端的css, js等代码发在app对应的static目录下,我们在模板中导入css或者js等代码的时候,引入{ %load static %}

跟templates类似,在多app下,我们通常会在每个app下创建一个static的文件夹,再创建对应app名字的文件件,将该app下使用的静态文件放在该目录

 

 

 

 

posted on 2022-11-16 15:21  阿明明  阅读(56)  评论(0编辑  收藏  举报