Django之模板层

模板层

常用语法

只需要两种特殊符号:{{}}{% %}

  • 变量相关的用{{}}
  • 逻辑相关的用{% %}

注释

注释是代码之母:

  • 单行注释:{# #}

  • 多行注释:

1 {% comment %}
2    <注释内容>
3 {% endcomment %

 注:模板语法的注释前端无法查看。

模板语法之传值

python基本数据类型传值

# 视图层

from django.shortcuts import render


def index_func(request):
    i = 666
    f = 11.11
    s = 'hello world'
    l = [111, 222, 333, 444]
    d = {'username': 'alex', 'password': 123, 'hobby': ['read', 'study', 'run']}
    t = (111, 222, 333)
    se = {111, 222, 333}
    b = True
    b1 = False
    # 传值方式1:指名道姓,利用字典挨个传值
    return render(request, 'indexPage.html', {'i': i, 'f': f, 's': s})
    # 传值方式2:简单粗暴  locals()将当前名称空间中所有的变量名全部传递给页面
    return render(request, 'indexPage.html', locals())

# 模板层

<body>
    <p>{{ i }}</p>
    <p>{{ f }}</p>
    <p>{{ s }}</p>
    <p>{{ l }}</p>
    <p>{{ d }}</p>
    <p>{{ t }}</p>
    <p>{{ se }}</p>
    <p>{{ b }}</p>
    <p>{{ b1 }}</p>
</body>

效果展示:

传值方式的优缺点:

  • 传值方式一:传值精确,不会造成资源浪费
  • 传值方式二:传值粗糙,可能会造成一定的资源浪费

模板语法传值特性

点(.)在模板语言中有特殊的含义。
  • django模板语法取值只能采用 句点符(.)也就是点
  • 可以根据索引以及键取值,索引、键都可以无限制的点点点……

 # 视图层

def index_func(request):

    d = {'username': 'alex', 'password': 123, 'hobby': ['read', 'study', 'run']}

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

# 模板层

 <p>{{ d.hobby.2 }}</p>

{#获取字典里hobby对应的索引为2的数据#}

效果展示:

当模版系统遇到点("."),它将以这样的顺序查询:

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

文件对象传值

# 视图层

from django.shortcuts import render

def index_func(request):
   
    f_obj = open(r'C:\Users\独孤傲\Desktop\数学网站.docx','rb')
    return render(request, 'indexPage.html', locals())

# 模板层

<p>{{ f_obj }}</p>
<p>{{ f_obj.read }}</p>    {#文件对象也可以展示并调用方法#}

效果展示:

 

函数传值特性

 # 视图层

from django.shortcuts import render

def index_func(request):

    def func1():
        print('快过年了')
        return '要加油啊'
    return render(request, 'indexPage.html', locals())

# 模板层

<p>{{ func1 }}</p>

前端页面展示结果:

pycharm执行结果:

 说明:函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参)

 

 类的传值特性

 # 视图层

def index_func(request):

    class MyClass(object):
        def get_obj(self):
            return '绑定给对象的方法'
        @classmethod
        def get_cls(cls):
            return '绑定给类的方法'
        @staticmethod
        def get_static():
            return '静态方法'

    obj = MyClass()

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

# 模板层

<p>{{ MyClass }}</p>
<p>{{ obj }}</p>

展示结果:

从上面的结果发现:

  • 类和类产生的对象展示的结果是一样的,都是一个对象,说明类名也会自动加括号调用,对象则不会。
  • 对象还可以继续通过点的方式调用方法。

模板语法之过滤器(内置函数)

Django的模板语言中,通过使用 过滤器 来改变变量的显示,大约有60种过滤器,这里只介绍常用过滤器。

模板语法

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

eg:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。

# 视图层:

def index(request):
    # python基本数据类型
    i = 666
    f = 11.11
    s = 'hello world 干饭人 干饭魂 我们都是打工人!'
    l = [111, 222, 333, 444]
    d = {'username': 'alex', 'password': 123, 'hobby': ['read', 'study', 'run']}
    t = (111, 222, 333)
    se = {111, 222, 333}
    w = 'aa bb cc dd ee ff'
    b = True
    b1 = False
    file_size= 2384024
    return render(request, 'index.html', locals())

常见过滤器

# 模板层:

<body>
{#        类似于python的内置方法#}
    <p>过滤器:将竖杆左侧的数据当做第一个参数</p>
    <p>统计长度:{{ s|length }}</p>
    <!-- add数字相加,字符拼接-->
    <p>加法运算:{{ i|add:100000000000 }}</p>
    <p>字符串拼接:{{ s|add:'heiheihei' }}</p>
    <p>拼接:{{ s|join:'@' }}</p>
    <p>切片:{{ l|slice:'0:5:2' }}</p>
    <p>日期格式:{{ ctime|date:'Y年-m月-d日 H时:i分:s秒' }}</p>
    <!-- 如果第一个参数的布尔值是true则显示左边的值,否则显示default后的值-->
    <p>默认值:{{ b|default:'哈哈' }}</p>
    <p>默认值:{{ b1|default:'哈哈' }}</p>
    <!-- 截取内容包含三个点,并且算在字符个数之内-->
    <p>文件大小:{{ file_size|filesizeformat }}</p>
    <p>截取文本(三个点也算):{{ s|truncatechars:6 }}</p>
    <!-- 截取内容包含三个点,但不算在单词个数之内,单词识别是以空格来区分的-->
    <p>截取文本(三个点不算)空格:{{ s|truncatewords:3 }}</p>

</body>

展示结果:

注意事项:

  • 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
  • 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
  • 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:’, ’ }}
  • '|'左右没有空格没有空格没有空格

转义(safe过滤器)

Django 会自动对 views.py 传到HTML文件中的标签语法进行转义,令其语义失效。加 safe 过滤器是告诉 Django 该数据是安全的,不必对其进行转义,可以让该数据语义生效。

# 视图层:

from django.shortcuts import render


def index_func(request):

    h1 = '<h1>哈哈哈哈哈哈</h1>'
    views_str = "<a href='https://www.baidu.com'>点我进入百度</a>"
    return render(request, 'indexPage.html', locals())

 

# 模板层:

<p>{{ h1 }}</p>
<p>{{ views_str }}</p>

 

展示结果:

 加 safe 过滤器之后:

<p>{{ h1|safe }}</p>
<p>{{ views_str|safe }}</p>

展示结果:

总结:前端代码不一定非要在前端页面写,可以在后端写好后传递给前端页面使用,这样的话,你就可以利用到后端更加多的逻辑语法。

 

模板层之标签

模板中的for循环

{% for 循环变量  in  循环对象  %}

        循环执行的语句

{%empty%}
        
        循环对象本身是空的时候,执行的代码

{% endfor%} {# 结束循环 #}

 

模板中的判断语句

{{% if 条件1(可以自己写也可以用传递过来的数据) %}
        
    <p>满足条件1执行的语句</p>

{% elif 条件2(可以自己写也可以用传递过来的数据) %}
        
    <p>满足条件2执行的语句</p>

{% else %}
        
    <p>以上条件都不满足时执行的语句</p>

{% endif %}

示例

# 视图层

from django.shortcuts import render


def index_func(request):

    l = [111,222,333,444,555,666]
    return render(request, 'indexPage.html', locals())

# 模板层

    {% for k in l %}
        {% if forloop.first %}
            <p>这是我的第一次循环{{ k }}</p>

        {% elif forloop.last %}
            <p>这是我的最后一次循环{{ k }}</p>
        
        {% else %}
            <p>这是中间循环{{ k }}</p>
        {% endif %}
        
        {% empty %}
            <p>你给我传的数据是空的无法循环取值(空字符串、空列表、空字典)</p>
    {% endfor %}

展示结果:

补充:

{% for %}标签内部模板变量forloop

  在{% for %}循环内部,可以访问一个名为forloop的模板变量。这个变量有若干属性,通过它们可以获知循环进程的一些信息。

forloop.counter
forloop.counter 的值是一个整数,表示循环的次数。这个属性的值从 1 开始,因此第一次循环时,forloop.counter 等于 1 。

forloop.first
forloop.first 是个布尔值,第一次循环时为 True 。

 

起别名(了解)

复杂数据获取之后需要反复使用可以起别名

d = {'name':'alex', 'age':18, 'hobby':['read','study',{'else':'sleep'}]}

{% with d.hobby.2.else as else_hobby %}
    {{ hobby }}
    {{ else_hobby }}
{% endwith %}

# 别名只可以在with里面用,with外面就失效了

自定义过滤器、标签及inclusion_tag(了解)

类似于python里面的自定义函数

1. 前期准备工作:

  1. 在应用下创建一个名字必须叫"templatetags"文件夹

  2. 在上述文件夹内创建一个任意名称的py文件

  3. 在该py文件内固定先书写以下两句话

from django import template
register = template.Library()

2.自定义过滤器

  • 自定义过滤器最多只能有两个形参
# 在模板层导入自定义的过滤器时使用的是这里指定的名字
@register.filter(name='myfilter')  
def sums(a, b):   # 函数名随便起什么
    return a + b  # 返回两个参数的和

#模板层
{% load mytags %}  # 导入tags文件
<p>{{ i|myfilter:100 }}</p>  # 使用myfilter过滤器

3.自定义标签simple_tag

  • 自定义标签可以有多个参数
# 自定义标签(参数没有限制)
@register.simple_tag(name='my_tag') # 在模板层导入自定义的标签时使用的是这里指定的名字 def my_join(a,b,c,d): # 函数名任意 return f'{a}/{b}/{c}/{d}' # 返回参数拼接后的结果 # 模板层: {% load mytags %} {% my_tag 'aaa' 'bbb' 'ccc' 'ddd' %} # 参数之间用空格隔开

4.自定义inclusion_tag

  • 当一些数据在前端的很多页面上需要反复使用,并且可以在前端通过传不同的参数渲染不同的结果,那么就可以制作一个inclusion_tag。
  • inclusion_tag的使用可以帮我们减少很多前端和后端重复的代码

inclusion_tag 的内部原理:

  • 前端某个HTML页面调用inclusion_tag
  • 触发了py文件中一个函数的执行,通过函数的逻辑处理并产生一些数据
  • 产生的数据通过模板语法传递给一个局部HTML页面进行渲染
  • 渲染完毕后又返回调用inclusion_tag的位置进行展示

 

 # 自定义inclusion_tag的py文件

@register.inclusion_tag('menu.html',name='mymenu')    # 第一个参数是需要渲染的HTML页面
def func(n):
    html =[]
    for i in range(n):
        html.append('<li>第%s页</li>'%i)
    return locals()  # 将数据传给局部HTML页面

# 局部页面(menu.html)

<ul>
    {% for liStr in html %}  # 接收函数传递过来的数据
        {{ liStr|safe }}
    {% endfor %}
</ul>

# 真正要使用数据的前端页面

{% load mytags %}   # 导入编写inclusion_tag的页面
{% mymenu 10 %}  # 导入局部页面并传参

模板的继承与导入

模板的继承

  • 模板的继承首先需要选择一个母板页面, 在该页面里面使用 block 划定可以被更改的区域
# 母板页面 'home.html' 文件
{% block [区域名称] %}    # 区域名称自己取
......                   # 这部分为划分出来的区域,可以在子板中进行修改
{% endblock %}
  • 想要继承的页面可以使用 extends 来继承某一个页面
# 子版
{% extends 'home.html' %}
{% block [区域名称] %}    # 与母版中划分出来的区域名称一致
......                   # 自己可以另外设计样式
{% endblock %}

子版继承了母板, 那么子版的整体格式与母板一样, 被 block 划分了的区域可以自己随意更改

母板的三个区域

  • 母板在划分区域的时候一般有三个区域
{% block css %}
    # css区域
{% endblock %}

{% block content %}
    # HTML区域
{% endblock %}

{% block js %}
    # js区域
{% endblock %}

总结:

  • 在母板中可以定义块,子类可以重写该部分内容。
  • 模板继承也是为了重用html页面内容,并且具有独立的css、js等,减少代码的冗余,同时增加扩展性

模板的导入

  • 将某个html的部分提前写好,之后很多html页面想使用就直接导入,类似于后端的模块。
# 被导入的myform.html(是一个局部页面)
{% include 'myform.html' %} # 把'myform.html'的页面导入到你想使用的页面

 与inclusion_tag很像,但inclusion_tag的参数可以动态获取,这个数据是写死的。

posted @ 2022-12-14 20:07  莫~慌  阅读(82)  评论(0编辑  收藏  举报