• Django 模板层


    Django模板层

       模板层的主要任务就是如何将页面呈现给用户,用户能看到的所有东西都是属于模板层进行呈现的。

       HTML文件就是模板,模板是会先经过渲染,再呈现给用户。

       学习模板层主要有以下两点:

       变量相关或处理均使用{{}},即模板变量。

       逻辑相关或处理均使用{%%},即模板标签。

    模板变量传值

       其实在聊Django视图层的时候介绍的render()方法中就允许将视图函数中的变量传递给模板。

       模板中使用{{name}}即可完成调用。

    def test(request):
        username = "云崖先生"
        return render(request,"test.html",locals())
    
    <body>
        {{username}}
    </body>
    

    传值类型

       Python中所有基本数据类型均可以进行模板传递,但是函数、类等可调用类型会出现一些令人意外的情况。

       注意:可调用类型传递时会自动加括号调用,并将返回值进行渲染(如果没有返回值则为None),但是不支持参数的传递。

       后端返回:

    def test(request):
    
        STR = "云崖先生"
        INT = 100
        FLOAT = 11.11
        BOOL = True
        DICT = {"v1":"k1"}
        SET = {"1","2","3"}
        TUPLE = (1,2,3)
        LIST = [1,2,3,4]
    
        def func():
            return "function"
    
        class T1(object):
            pass
    
        return render(request,"test.html",locals())
    
    

       模板接收:

    <body>
    
        <p>{{STR}}</p>
        <p>{{INT}}</p>
        <p>{{FLOAT}}</p>
        <p>{{BOOL}}</p>
        <p>{{DICT}}</p>
        <p>{{SET}}</p>
        <p>{{TUPLE}}</p>
        <p>{{LIST}}</p>
        <p>{{func}}</p>  <!-- 不支持参数传递 -->
        <p>{{T1}}</p>  <!-- 实例化出了一个类 -->
        
    </body>
    

       渲染结果:

    云崖先生
    
    100
    
    11.11
    
    True
    
    {'v1': 'k1'}
    
    {'1', '2', '3'}
    
    (1, 2, 3)
    
    [1, 2, 3, 4]
    
    function
    
    <app01.views.test.<locals>.T1 object at 0x000001C1E00ACB38>
    

    元素取出

       无论后端的变量是list或者dict,均可使用.语法进行取值。

    传值:
    def test(request):
    
        DICT = {"hobby":["basketball","football","volleyball"]}
    
        return render(request,"test.html",locals())
        
    
    取值:
    {{DICT.hobby.2}}
    
    结果:
    volleyball
    

    模板变量过滤

       由于后端的函数模板中使用函数无法传递参数,所以提供自带的过滤器进行操作。

       过滤器有非常多的功能,大概有六十多种过滤器提供使用,这里只介绍常用的。

    使用示例

       以下举例常用的模板过滤器

    过滤器描述
    {{v1|length}} 获取v1的长度
    {{v1|default:v2}} 如果v1为真,则使用v1,否则使用v2
    {{v1|filesizeformat}} v1必须是int类型,对其进行KB、MB、GB、TB等进制之间的转换
    {{v1|date:"Y-m-d X"}} v1必须是时间类型,对其进行自定义格式化
    {{v1|slice:"start:stop:step"}} v1必须是可通过索引取值的类型,对其进行切片
    {{v1|truncatechars:num}} v1必须是可通过索引取值的类型,对其截取指定长度的字符(包含三个.
    {{v1|truncatewords:num}} v1必须是字符串类型,对其进行截取特点数量的单词,以空格分隔(不包含.
    {{v1|cut:'v2'}} 移除v1中特定的字符v2
    {{v1|join:'v2'}} 使用v2对v1进行拼接
    {{v1|add:v2}} v1与v2进行相加,如都是int则为加法,如都是str则为拼接
    {{v1|safe}} 识别v1中的HTML代码并进行渲染(默认不会进行渲染)

       后端返回:

    def test(request):
        import datetime
        v_1 = "12345"
        v_2 = False
        v_3 = 10240
        v_4 = datetime.datetime.now()
        v_5 = ["一","二","三","四","五","六","七"]
        v_6 = "abcdefghijklmn"
        v_7 = "HELLO WORD HELLO DJANGO"
        v_8 = "ABC$$$"
        v_9 = "QWETYU"
        v_10 = 10
        v_11 = "<h1>标题一<h1>"
        return render(request,"test.html",locals())
    
    

       模板接收加过滤:

    <body>
    
       <p>{{v_1|length}}</p>
       <p>{{v_2|default:1}}</p>
       <p>{{v_3|filesizeformat}}</p>
       <p>{{v_4|date:"Y-m-d h:m:s"}}</p>
       <p>{{v_5|slice:"1:4:2"}}</p>
       <p>{{v_6|truncatechars:6}}</p> 
       <!-- 上面的: 三个点占三个位置 -->
       <p>{{v_7|truncatewords:3}}</p>
       <!-- 上面的:三个点不占位置 -->
       <p>{{v_8|cut:"$"}}</p>
       <p>{{v_9|join:"---"}}</p>
       <p>{{v_10|add:10}}</p>
       {{v_11|safe}}
    
    </body>
    

       渲染结果:

       image-20200910223625256

    后端渲染

       默认的,后端如果返回HTML代码模板层是不会进行渲染的,这是为了防止XSS攻击。

       但是如果使用mark_safe()进行包裹,则会进行渲染。

      

    def test(request):
    
        from django.utils.safestring import mark_safe # 导入模块
        
        res = "<h1>不会渲染<h1>"
        res_safe = mark_safe("<h1>会渲染<h1>")
        return render(request,"test.html",locals())
    
    <body>
    
        {{res}}
        {{res_safe}}
    
    </body>
    

       image-20200910224438551

    模板标签分支

    基本使用

       模板中支持对{% if %}、{% else %}、{% elif %}进行使用,与Python中逻辑一致。

       注意:判断完成后要使用{% endif %}进行结束判断的标志

    <body>
    
        {% if user %} <!-- 在{%%}的模板标签中,被{{}}套住的变量可以不用写{{}}-->
            <p>有内容</p>
        {% else %}
            <p>无内容</p>
        {% endif %}
        
    </body>
    

    模板标签循环

    基本使用

       模板中支持{% for %}来进行操作。

       注意:循环完成后要使用{% endfor %}进行结束循环的标志

    li = ["A","B","C"]
    
    <body>
        
        {% for row in li %}
            <p> {{row}} </p> <!-- 在{%%}外使用变量,依然要嵌套上{{}} -->
        {% endfor %}
            
    </body>
    
    A
    
    B
    
    C
    

    forloop

       {{forloop}}记录了一些循环的信息。

       如下所示:

    li = ["A","B","C"]
    
    <body>
        
        {% for row in li %}
           <p> {{forloop}} </p> <!-- 可使用 {{forloop.counter/first/last}} 等 -->
        {% endfor %}
            
    </body>
    

       image-20200910230625903

    不可循环

       如果一个迭代对象为空,则不可循环。此时可以使用{% empty %}进行操作

    li = []
    
    <body>
    
        {% for row in li %}
        	<p>不为空</p>
        {% empty %}
        	<p>迭代对象为空</p> <!--执行这里-->
        {% endfor %}
    
    </body>
    

    键值方法

       在循环中,可以对被遍历的对象使用keys、values、items进行操作。

       这与Python中是一样的。

    dic = {"name":"云崖","age":"18","gender":"男",}
    
    <body>
    
        {% for key in dic.keys %}
            <p>{{key}}</p>
        {% endfor %}
    
        {% for value in dic.values %}
            <p>{{value}}</p>
        {% endfor %}
    
        {% for kv in dic.items %}
            <p>{{kv}}</p>
        {% endfor %}
    
    </body>
    
    ----------------
    name
    
    age
    
    gender
    ----------------
    云崖
    
    18
    
    男
    ----------------
    ('name', '云崖')
    
    ('age', '18')
    
    ('gender', '男')
    

    模板标签别名

       可以使用{% with %}配合as对嵌套复杂的单项数据做一个别名。方便后续进行拿出,更推荐与循环进行配套使用。

    li = [
    	{"username":"Yunya"},
    	{"username":"Jack"},
    	{"username":"Tom"},
    ]
    
    ----------------
    
    <body>
    
        {% for row in li %}
    
            {% with row.username as data %}
                    <p>{{data}}</p>
                    <!-- 如果不使用别名,则需要写 {{row.username}} 这只是一个示例,实际的嵌套可能比这个复杂的多 -->
            {% endwith %}
            
        {% endfor %}
            
    </body>
    
    ----------------
    
    Yunya
    
    Jack
    
    Tom
    

    自定义系列

       所有的,自定义都需要完成以下三步骤:

       1.在APP中创建templatetags文件夹,必须叫这个名字

       2.在该文件夹下创建一个py文件,可以是任意名字

       3.导入一个模块,并写一句话

       from django import template

       register = template.Library()

    自定义过滤器

       先完成上面三步,再进行过滤器的创建。

       自定义过滤器的作用就是丰富内置的过滤器,完成你的需求。

       注意:过滤器的调用是{{ v1|filter:v2 }},过滤器最多只能传递两个参数,且第一个参数在|左边,第二个参数传递的格式必须是过滤器名字:右边的参数。

       自定义过滤器全步骤:

    # app01/templatetags/tags.py
    
    from django import template
    register = template.Library()
    
    
    @register.filter(name="f1")  # 在使用时,使用的是这个名字。函数名可以随便取。注意一定要关键字传参
    def f1(left, right):  # left 代表斜杠左边的值,right代表斜杠右边的值
        return left + right
    
    

       基本使用:

    <body>
    
        {% load tags %}  <!-- 先导入标签的文件,tags.py -->
        {{1|f1:2}} <!-- 最多两个参数,参数1|过滤器名字:参数2  这是固定格式
            
    </body>
    
    -------
    
    3
    

    自定义标签

       自定义标签与自定义过滤器比较相似但是也有两大不同。

       1.支持无限制的参数传递

       2.参数传递方式不同

       注意:标签的调用是{% tag v1 v2 v3 %},这与过滤器有较大的不同。

       先完成上面三步,再进行标签的创建。

    # app01/templatetags/tags.py
    
    from django import template
    register = template.Library()
    
    
    @register.simple_tag(name="t1")  # 在使用时,使用的是这个名字。函数名可以随便取。注意一定要关键字传参
    def t1(v1, v2, v3):
        return v1 + v2 + v3
    

       基本使用:

    <body>
    
        {% load tags %} <!-- 先导入标签的文件,tags.py -->
        {% t1 1 2 3%} <!--参数无限制-->
            
    </body>
    

    自定义inclusion_tag

       自定义inclusion_tag与上面两个都不太一样,它返回的是一个局部页面,当你的项目中有很多网页中都有相同的一部分网页结构,则使用自定义inclusion_tag来完成。

       还是需要先完成上面三个步骤。

    # app01/templatetags/tags.py
    
    from django import template
    register = template.Library()
    
    @register.inclusion_tag("common.html") # 去根目录找templates文件夹下的common.html文件
    def common_html(username): # 注意,这里调用是函数名,而不是上面指定的名字了
        user = username
        return locals() # 返回当前命名空间中所有变量名
    
    # 项目根目录/templats/common.html
    
    <h1>当前登录:{{user}}</h1> # 可以拿到 common_html 函数中的所有变量名了
    <h1>点击注销</h1>
    
    # 被渲染的模板
    
    <body>
    
        {% load tags %}
        {% common_html "云崖" %} <!---这一处将会替换为指定的页面,即common.html里的内容-->
            
    </body>
    

    模板继承引入

    模板继承

       模板继承是全栈开发里面Django所提供的非常牛逼的一个功能,它允许你一套HTML模板能被其他模板进行继承并修改一些特定区域的内容。

       image-20200911004024841

    # 项目根目录/templats/common.html
    
    {% block left %}
    <!-- 这里面可以允许修改,相当于给这块区域起一个名字,left -->
    
    {% endblock %}
    
    ============================
    
    # 项目根目录/templats/other.html
    
    {% extends 'common.html' %}
    <!-- 继承common.html -->
    
    {% block left %}
    <!-- 执行修改 -->
    
    {% endblock %}
    

       接下来看一下演示代码就知道了。

       这里放一套公用的左右布局页面

    # 项目根目录/templats/common.html
    
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js'></script>
        <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css'
            integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u' crossorigin='anonymous'>
        <script src='https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js'
            integrity='sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa'
            crossorigin='anonymous'></script>
        <title>Document</title>
        
        {% block CSS %}
            
        {% endblock %}
            
    </head>
    
    <body>
    
        <header class="navbar navbar-inverse">
            <!-- 头部,不允许改变 -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">Project name</a>
            </div>
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Home</a></li>
                    <li><a href="#about">About</a></li>
                    <li><a href="#contact">Contact</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                            aria-expanded="false">Dropdown <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li class="dropdown-header">Nav header</li>
                            <li><a href="#">Separated link</a></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="../navbar/">Default</a></li>
                    <li><a href="../navbar-static-top/">Static top</a></li>
                    <li class="active"><a href="./">Fixed top <span class="sr-only">(current)</span></a></li>
                </ul>
            </div>
        </header>
        <main class="container-full">
    
            <div class="row">
                <section class="col-sm-3 col-md-2 sidebar">
                    <!-- 左边,允许改变一小块区域 -->
          
                        <ul class="nav nav-sidebar">
                            <li class="active"><a href="#">menu1 <span class="sr-only">(current)</span></a></li>
                            <li><a href="#">menu2</a></li>
                            <li><a href="#">menu3</a></li>
                            <li><a href="#">menu4</a></li>
                        </ul>
                        {% block left %}
                        <!-- 这里面可以允许修改,相当于给这块区域起一个名字,left -->
     
                        {% endblock %}
    
    
                </section>
    
                <section class="col-lg-6">
    
                    {% block right %}
                    <!-- 这里面可以允许修改,相当于给这块区域起一个名字right -->
           
    
                    {% endblock %}
    
                </section>
            </div>
    
        </main>
    
    </body>
    
    {% block Js %}
        
    {% endblock %}
    
    </html>
    
    # 项目根目录/templats/其他页面.html
    
    {% extends 'common.html' %}
    <!-- 继承common.html -->
    
    {% block left %}
    <!-- 修改内容 -->
    <ul class="nav nav-sidebar">
        <li><a href="">menu-div-1</a></li>
        <li><a href="">menu-div-2</a></li>
        <li><a href="">menu-div-3</a></li>
    </ul>
    {% endblock %}
    
    {% block right %}
    <!-- 修改内容 -->
        <h4>Subheading</h4>
        <p>Donec id elit non mi porta gravida at eget metus. Maecenas faucibus mollis interdum.</p>
    
        <h4>Subheading</h4>
        <p>Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras mattis consectetur purus sit amet fermentum.</p>
    
        <h4>Subheading</h4>
        <p>Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
    
    {% endblock %}
    
    {% block css %}
    <!-- 修改CSS -->
    {% endblock %}
    
    {% block js %}
    <!-- 修改Js -->
    {% endblock %}
    

    模板引入

       模板引入是在一个HTML中引入一段公用的HTML代码。

    # 项目根目录/templats/common.html
    
    <h1>公用咯<h1>
    
    ============================
    
    # 项目根目录/templats/other.html
    
    {include "common.html"}  <!-- 将common.html中代码全部拿过来 -->
    
    
  • 相关阅读:
    linux指令大全
    strcpy.strcmp.strlen.strcat函数的实现
    推箱子
    头文件string.h里的函数
    SVN 版本控制工具
    Nodejs 学习
    JavaScript基础知识复习
    CSS3 学习小结
    JSP中 JSTL
    JSP中的EL语言
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13691035.html
Copyright © 2020-2023  润新知