模板层Templates

发布时间 2023-04-27 21:28:44作者: 星空看海

模板层

Django提供了模板系统 (Template System)用来专门定制html文件,一个html文件称之为一个模板

  • 对于静态页面来说,直接编写就好

  • 而针对动态页面,django额外提供了专门的模板语言(Django template language,简称DTL),允许我们在页面中嵌入模板变量,这便为后期为页面动态填充内容提供了可能性。

    DTL是模板系统的核心,因此django的模板系统也被等同于DTL

模板语法的使用

模板语法传值

方式一:字典

return render(request, 'demo02.html', {'n1': name, 'a1': age})  # 传值方式1:精准传值,不浪费资源,针对多资源的传递书写麻烦

方式二:locals()

return render(request,'demo02.html', locals())  # 传值方式2:将函数名称空间中所有的名字全部传递,名字过多并且不使用的情况下比较浪费资源
locals():当前函数中的所有局部变量,并且组装成字典的形式

变量

  • {{}}:主要与数据值相关,跟变量相关
  • {%%}:主要与逻辑相关

传值的特性:

1.基本数据类型正常展示
2.文件对象也可以展示并调用方法,模板语法会自动加括号
3.函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参)
4.类名也会自动加括号调用,产生一个对象
5.对象则不会	
"""
1.模板语法中取值使用点语法
2.针对需要加括号调用的名字,django模板语法会自动加括号调用,你直接写函数名就行
3.模板语法的注释前端浏览器是无法查看的,地下控制台查看不到 {##}
"""

基本使用:

views.py

# 模板语法
def template_func(request):
    # python基本数据类型
    f = 1.11
    i = 666
    s = 'hello world'
    lst = [1, 2, 3, 4]
    d = {'name': 'jason', 'age': 18}
    t = (11, 22, 33, 44)
    se = {666, 333, 999, 222}
    b = True

    # 函数
    def func():
        return 'func函数'

    # 类
    class Login():
        def __init__(self, name):
            self.name = name

        def get_obj(self):
            return '绑定给对象的方法'

        @classmethod
        def get_cls(cls):
            return '绑定给类的方法'

        @staticmethod
        def get_static():
            return '静态方法'

    obj = Login('http')  # 对象

    return render(request, 'template.html', locals())

html:

<p>{{ f }}</p>
<p>{{ i }}</p>
<p>{{ s }}</p>
<p>{{ lst }}</p>
<p>{{ d }}</p>
<p>{{ t }}</p>
<p>{{ se }}</p>
<p>{{ b }}</p>
{# 函数 #}
<p>{{ func }}</p>
<p>{{ Login }}</p>{# 类名 #}

深度查询之句点符的使用

变量名中不能有空格或者标点符号,但是有一个例外,点(".")可以出现在变量中,点后的可以是字典相关(字典的key或者字典内置方法)、对象的属性或方法、数字索引,如下所示

<hr>
<h3>深度查询句点符</h3>
<p>{{ lst.0 }}</p>  {# 列表.索引 #}
<p>{{ d.age }}</p>  {# 字典.key #}
<p>{{ obj.name }}</p>  {# 对象.属性 #}
<p>{{ obj.get_obj }}</p>  {# 对象.方法 #}
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_static }}</p>

过滤器

过滤器类似于python的内置函数,用来把变量值加以修饰后再显示,具体语法如下

#1、
{{ 变量名|过滤器名 }}

#2、链式调用:上一个过滤器的结果继续被下一个过滤器处理
{{ 变量名|过滤器1|过滤器2 }}

#3、有的过滤器取需要参数
{{ 变量名|过滤器名:传给过滤器的参数 }}

常用内置过滤器

#0、default
#作用:如果一个变量值是False或者为空、None,使用default后指定的默认值,否则,使用变量本身的值,如果value=’‘则输出“nothing”
{{ value|default:"nothing" }}

#1、default_if_none
#作用:如果只针对value是None这一种情况来设置默认值,需要使用default_if_none
#只有在value=None的情况下,才会输出“None...”,
{{ value|default_if_none:"None..." }}

#2、length
#作用:返回值的长度。它对字符串、列表、字典等容器类型都起作用,如果value是 ['a', 'b', 'c', 'd'],那么输出是4
{{ value|length }}

#3、filesizeformat
#作用:将值的格式化为一个"人类可读的"文件尺寸(如13KB、4.1 MB、102bytes等等),如果 value 是 12312312321,输出将会是 11.5 GB
{{ value|filesizeformat }}

#4、date
#作用:将日期按照指定的格式输出,如果value=datetime.datetime.now(),按照格式Y-m-d则输出2019-02-02
{{ value|date:"Y-m-d" }}  

#5、slice
#作用:对输出的字符串进行切片操作,顾头不顾尾,如果value=“egon“,则输出"eg"
{{ value|slice:"0:2" }} 

#6、truncatechars
#作用:如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾,如果value=”hello world egon 嘎嘎“,则输出"hello...",注意8个字符也包含末尾的3个点
{{ value|truncatechars:8 }}

#7、truncatewords
#作用:同truncatechars,但truncatewords是按照单词截断,注意末尾的3个点不算作单词,如果value=”hello world egon 嘎嘎“,则输出"hello world ..."
{{ value|truncatewords:2 }}

后端也可以处理前端的标签

from django.utils.safestring import mark_safe
ss = mark_safe('<h1>hello</h1>')
# 后端处理前端的问题:是把前端的当成字符串来处理

示例:

views.py

def template_func(request):
    # 过滤器
    de = []
    de1 = [4, ]
    fa = False
    file_data = 5952628

    # 日期
    from datetime import date, datetime
    ctime1 = date.today()
    ctime2 = datetime.today()
    s1 = 'hello world lqz khn uvr cbjkgra'

    h1 = '<h1>哈哈哈哈</h1>'
    s1 = "<script>confirm(123)</script>"

    # 后端也可以处理前端的标签
    from django.utils.safestring import mark_safe
    ss = mark_safe('<h1>hello</h1>')
    # 后端处理前端的问题:是把前端的当成字符串来处理

    return render(request, 'template.html', locals())

html

<h3>过滤器</h3>
{# 增加数字,拼接字符 #}
<p>{{ i|add:30 }}</p>
<p>{{ s|add:'hahaha' }}</p>

{#如果变量为空,设置默认值,空数据,None,变量不存在,都使用给定的默认值。否则,使用变量的值。#}
<p>{{ de|default:"空列表" }}</p>
<p>{{ de1|default:"空列表" }}</p>
<p>{{ fa|default:"假的" }}</p>
{# 计算长度,只有一个参数 #}
<p>{{ lst|length }}</p>
{# 计算文件大小 #}
{#单位换算展示,可以自己转换成最合适的单位#}
<p>{{ file_data|filesizeformat }}</p>
{# 日期 #}
<p>{{ ctime1|date:'Y-m-d' }}</p>
<p>{{ ctime2|date:'Y年-m月-d日 H时:i分:s秒' }}</p>

{# 字符串切片 #}
<p>{{ s1|slice:"2:-1" }}</p>
<p>{{ s1|slice:"2:5" }}</p>

{#截断字符,至少三个起步,因为会有三个省略号 #}
<p>{{ s1 |truncatechars:"6" }}</p>
{# hel... #}

{#截断文字,以空格做区分,这个不算省略号#}
<p>{{ s1 |truncatewords:"3" }}</p>
{# hello world lqz ... #}

<p>{{ h1 }}</p>  {# 默认是不识别的 #}
<p>{{ s1 }}</p>
<p>{{ h1|safe }}</p>
<p>{{ s1|safe }}</p>

<p>{{ ss }}</p>

    
{# 大写和小写 #}
<p>{{ 'name'|upper }}</p>
<p>{{ 'LQZ'|lower }}</p>

其他过滤器(了解)

详见官网:https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#ref-templates-builtins-filters

过滤器 描述 示例
upper 以大写方式输出 {{ user.name
add 给value加上一个数值 {{ user.age
addslashes 单引号加上转义号
capfirst 第一个字母大写 {{ ‘good’
center 输出指定长度的字符串,把变量居中 {{ “abcd”
cut 删除指定字符串 {{ “You are not a Englishman”
date 格式化日期 default_if_none 如果值为None, 则使用默认值代替
dictsort 按某字段排序,变量必须是一个dictionary {% for moment in moments
dictsortreversed 按某字段倒序排序,变量必须是 dictionary
divisibleby 判断是否可以被数字整除 {{ 224
escape 按HTML转义,比如将”<”转换为”<”
filesizeformat 增加数字的可读性,转换结果为13KB,89MB,3Bytes等 {{ 1024 filesizeformat }} 返回 1.0KB
first 返回列表的第1个元素,变量必须是一个列表
floatformat 转换为指定精度的小数,默认保留1位小数 {{ 3.1415926 floatformat:3 }} 返回 3.142 四舍五入
get_digit 从个位数开始截取指定位置的数字 {{ 123456
join 用指定分隔符连接列表 {{ [‘abc’,’45’]
length 返回列表中元素的个数或字符串长度
length_is 检查列表,字符串长度是否符合指定的值 {{ ‘hello’
linebreaks 用或 标签包裹变量 {{ “Hi\n\nDavid”
linebreaksbr 用 标签代替换行符
linenumbers 为变量中的每一行加上行号
ljust 输出指定长度的字符串,变量左对齐 {{‘ab’
lower 字符串变小写
make_list 将字符串转换为列表
pluralize 根据数字确定是否输出英文复数符号
random 返回列表的随机一项
removetags 删除字符串中指定的HTML标记 {{value
rjust 输出指定长度的字符串,变量右对齐
slice 切片操作, 返回列表 {{[3,9,1]
slugify 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 {{ '5-2=3and5 2=3'
stringformat 字符串格式化,语法同python
time 返回日期的时间部分
timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量
title 每个单词首字母大写
truncatewords 将字符串转换为省略表达方式 {{ 'This is a pen'
truncatewords_html 同上,但保留其中的HTML标签 {{ '
This is a pen
' truncatewords:2 }}返回``
This is ...
urlencode 将字符串中的特殊字符转换为url兼容表达方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’
urlize 将变量字符串中的url由纯文本变为链接
wordcount 返回变量字符串中的单词数
yesno 将布尔变量转换为字符串yes, no 或maybe {{ True
yesno
maybe

标签

模板中的标签的格式为

# 1、
{% 标签名 %}

# 2、大多数标签都需要接收参数
{% 标签名 参数1 参数2 %}

# 3、一些标签需要有开始{% tag %}和结束标记{% endtag %}
{% 标签名 %}
...内容...
{% end标签名 %}

for标签

1、遍历每一个元素:

{% for i in lst %}
    <p>{{ i }}</p>
{% endfor %}

2、遍历一个字典:

{% for key in d %}
    <p>{{ key }}</p>
{% endfor %}

3、字典的三剑客

{# keys values items #}

{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}

{% for foo in d.values %}
    <p>{{ foo }}</p>
{% endfor %}

{% for foo in d.items %}
    <p>{{ foo }}</p>
    {# 取元组内部的值 #}
    {# <p>{{ foo.0 }}</p> #}
{% endfor %}

{% for key,val in d.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}

结果为:

name
age
gender

jason
18
famale

('name', 'jason')
('age', 18)
('gender', 'famale')

name:jason
age:18
gender:famale

4、循环序号可以通过{{ forloop }}显示 

forloop.counter            The current iteration of the loop (1-indexed) 当前循环的索引值(从1开始)
forloop.counter0           The current iteration of the loop (0-indexed) 当前循环的索引值(从0开始)
forloop.revcounter         The number of iterations from the end of the loop (1-indexed) 当前循环的倒序索引值(从1开始)
forloop.revcounter0        The number of iterations from the end of the loop (0-indexed) 当前循环的倒序索引值(从0开始)
forloop.first              True if this is the first time through the loop 当前循环是不是第一次循环(布尔值)
forloop.last               True if this is the last time through the loop 当前循环是不是最后一次循环(布尔值)
forloop.parentloop         本层循环的外层循环

具体使用:

{% for foo in lst %}
    <p>{{ forloop }}</p>

    {# 还可以用点语法取出内部的属性 #}
    {#<p>{{ forloop.counter0 }}</p>#}

{% endfor %}

5、for … empty
循环的值是空,就执行empty里面的内容

lst = []


{% for foo in lst %}
    <p>{{ foo.name }}</p>
{% empty %}
    <p>列表为空</p>
{% endfor %}

if 标签

# {% if %}会对一个变量求值,如果它的值是True(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

{% if num > 100 or num < 0 %}
    <p>无效</p>
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}
    <p>凑活吧</p>
{% endif %}

# if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

with起别名

d = {'username':'kevin','age':18,'info':'这个人有点意思','hobby':[111,222,333,{'info':'NB'}]}


{% with d.hobby.3.info as nb  %}
    <p>{{ nb }}</p>
    在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
    <p>{{ d.hobby.3.info }}</p>{# 与上面是等价的#}
{% endwith %}


csrf_token标签

之前提交方式是post就需要去settings中注释一行,现在可以在form表单中设置,就可以提交了。

<form action="" method="post">
    {% csrf_token %}
    <input type="submit">

结果:

前端Elements控制台中会直接变成:

<input type="hidden" name="csrfmiddlewaretoken" value="1sWyohvTZjU4xicEYLkbZRA01EbJxG3HNyBuBxfmezVD8PMv4EJIsd185cLQa5vA">

更多内置标签与过滤器:https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#ref-templates-builtins-tags

模板的导入和继承

在实际开发中,模板文件彼此之间可能会有大量冗余代码,为此django提供了专门的语法来解决这个问题,主要围绕三种标签的使用:include标签、extends标签、block标签,详解如下

模板的继承之extends标签、block标签

模板中:

{% block 标记的名字 %}
	在模板中是把能够替换的内容直接放入block中,其他不要动
{% endblock %}

子模版:

{% extends 'home.html' %}
extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个home.html模版中的所有元素。


{% block 标记的名字 %}{# 直接拿这模板中的名字来改就行 #}
	子模版中替换的内容
{% endblock %}

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版替换的 block 。一个模板页面中也不要设置太多block。

被block标记的位置就是子模版可以替换的位置

# 一个模板页面中应该至少有3块内容可以被替换
1. css
2. js
3. html

具体使用:
模板html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    {% block css %}

    {% endblock %}
</head>
<body>
<div class="panel panel-primary">
    {% block aa %}
        <div class="panel-heading">py25的兄弟们最nb</div>
    {% endblock %}

    <div class="panel-body">
        {% block content %}
            <div class="jumbotron">
                <h1>洋哥带的学员最NB</h1>
                <p>...</p>
                <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
            </div>
        {% endblock %}
    </div>
</div>

{% block js %}

{% endblock %}
</body>
</html>

子模板:
更改模板中标记为block content的位置。

{% extends 'home.html' %}
{% block css %}
    <style>
        h1 {
            color: red;
        }
    </style>
{% endblock %}


{% block content %}
    <form action="">
        <h1>登录页面</h1>
        <p>username: <input type="text" class="form-control"></p>
        <p>password: <input type="text" class="form-control"></p>
        <p>
            <input type="submit" value="登录" class="btn btn-primary">
        </p>
        {% include 'welcome.html' %}

    </form>
{% endblock %}

{% block js %}
    <script>

    </script>
{% endblock %}

模板的导入之include标签

作用:在一个模板文件中,引入/重用另外一个模板文件的内容,

示例:
先写一个页面welcome.html

<h1>欢迎你的光临</h1>
<h1>欢迎你的光临</h1>

home.html:

 {% include 'welcome.html' %}

就代表把welcome.html中的所有内容都引入进来