• Django模板渲染


    django模板渲染

    模板渲染,模板指的就是html文件,渲染指的就是字符串替换,将模板中的特殊符号替换成相关数据

    基本语法

    {{ 变量 }}
    {% 逻辑 %}

    变量使用

    看示例

    Views.py文件

    def home(request):
        class A:
            def __init__(self):
                self.username = 'bob'
            #如果方法需要在模板中使用,那么不能有其他参数
            def xx(self):  
                
                return 'bobxx'
    
        info = {
            'name': 'jack',
            'hobby': ['running', 'walking', 'reading'],
            'num': 100,
            'd1':{'aa':'bb'},
            'l1':[11,22,{'cc':'dd'}],
            'a': A(),
        }
    
        return render(request, 'home.html', info)

    home.html内容如下

    重点:万能的据点号。通过点可以进行数据的索引取值,属性取值,取方法等等

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    <h2>{{ name }}</h2>
    
    <ul>
        {% for i in hobby %}
            <li>{{ i }}</li>
        {% endfor %}
    
    </ul>
    
    <hr>
    {{ num }}
    <p>
        {{ l1.2.ss }}
    </p>
    <p>
        {{ d1.xx }}
    </p>
    <p>
        {{ a.username }}
    </p>
    <p>
        {{ a.xx }} <!-- 方法不能加括号,意味着不能穿参数,也就是说你后面定义的方法,不能有参数 -->
    </p>
    
    </body>
    
    </html>

    urls.py内容

    url(r'^home/', views.home),

    过滤器

    在Django的模板语言中,通过使用 过滤器 来改变变量的显示。

    过滤器的语法:{{ value|filter_name:参数 }}

    使用过滤器的注意事项

    1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
    
    2. {{ sss|过滤器1:30|过滤器2.... }}
    
    3. 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
    
    4. '|'左右没有空格

     

    内置过滤器

    常用的内置过滤器示例

    (1) default

    如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。

    {{ value|default:"nothing"}}

    如果value没有传值或者值为空或者为False的话就显示nothing

    (2) length

    返回值的长度,作用于字符串和列表。

    {{ value|length }}

    返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

    (3) filesizeformat

    将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

    {{ value|filesizeformat }}

    如果 value 是 123456789,输出将会是 117.7 MB。

    (4) slice

    切片,如果 value="hello world",还有其他可切片的数据类型

    {{value|slice:"2:-1"}}
    (5) date

    格式化,如果 value=datetime.datetime.now(),如果不想显示为UTC时间,将django的settings.py配置文件中的TIME_ZONE这一项修改一下,修改为TIME_ZONE = 'Asia/Shanghai'

    比如,后台返回的数据为{'value':datetime.datetime.now()}

    对上面的数据进行格式化:{{ value|date:"Y-m-d H:i:s"}}

     关于时间日期的可用的参数(除了Y,m,d等等)还有很多,有兴趣的可以去查查看看。

    (6) safe

    xxs攻击,全称跨站脚本攻击    Django的模板中在进行模板渲染的时候会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全,django担心这是用户添加的数据,比如如果有人给你评论的时候写了一段js代码,这个评论一提交,js代码就执行啦,这样你是不是可以搞一些坏事儿了,写个弹窗的死循环,那浏览器还能用吗,是不是会一直弹窗啊,这叫做xss攻击,所以浏览器不让你这么搞,给你转义了。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

    {'a_tag':'<a href="">百度</a>',}
    
    渲染
    <p>
        {{ a_tag|safe }} #生成标签效果
    </p>
    (7) truncatechars

    如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

    参数:截断的字符数

    {{ value|truncatechars:9}} #注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,有人会说,怎么展开啊,配合前端的点击事件就行啦
    (8) truncatewords

    在一定数量的字后截断字符串,是截多少个单词。

    例如:‘are you ok’,

    {{ value|truncatewords:2}}  #上面例子得到的结果是 'are you...'

    (9) cut

    移除value中所有的与给出的变量相同的字符串

    {{ value|cut:' ' }}

    如果value为'i love you',那么将输出'iloveyou'.

    (10) join

    使用字符串连接列表,{{ list|join:', ' }},就像Python的str.join(list)

    <p>{{ hobby|join:'+' }}</p>

     

    注意:模版渲染在浏览器渲染之前,模板渲染就是字符串替换,替换完成之后,将替换完的整体文件字符串返回给浏览器,浏览器再进行浏览器渲染,展示页面效果

     

    标签

    语法{% 标签 %}

    (1) for循环标签

    示例:

    #循环列表
    <ul>
        {% for xx in hobby %}
        <li>{{ xx }}</li>
        {% empty %}  #当hobby为空或者后台没有给这个数据,那么会显示empty下面的内容
            <h2>抱歉,没有查询到相关数据</h2>
        {% endfor %}
    </ul>
    
    #循环字典
    <ul>
        {% for k,v in d1.items %}  <!-- 直接循环字典数据,那么是循环字典的key,循环d1.values,那么表示循环字典的值, 循环d1.items,那么k,v表示键和值-->
            <li>{{ k }}--{{ v }}</li>
        {% endfor %}
    
    </ul>
    
    #循环计数
    <ul>
    {% for i in l1 %}
    
    {#    {{ forloop }}#}
        {% for h in hobby %}
            <li>{{ forloop.parentloop.counter }}--{{ forloop.revcounter0 }}---{{ h }}--{{ forloop.last }}</li>
        {% endfor %}
    
    {% endfor %}
    </ul>
    
    forloop的解释
     注:循环序号可以通过{{forloop}}显示,必须在循环内部用 
    forloop.counter            当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
    forloop.counter0           当前循环的索引值(从0开始)
    forloop.revcounter         当前循环的倒序索引值(从1开始)
    forloop.revcounter0        当前循环的倒序索引值(从0开始)
    forloop.first              当前循环是不是第一次循环(布尔值)
    forloop.last               当前循环是不是最后一次循环(布尔值)
    forloop.parentloop         本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
      
    #反向循环
    可以利用{% for obj in list reversed %}反向完成循环。
    示例:
    <ul>
        {% for xx in hobby reversed %}
        <li>{{ xx }}</li>
        {% endfor %}
    </ul>

    (2) if 标签

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

    {% if num > 100 or num < 0 %}
        <p>无效</p>  <!--不满足条件,不会生成这个标签-->
    {% elif num > 80 and num < 100 %}
        <p>优秀</p>
    {% else %}  <!--也是在if标签结构里面的-->
        <p>凑活吧</p>
    {% endif %}

    当然也可以只有if和else

    {% if user_list|length > 5 %}  <!--结合过滤器来使用-->
      七座豪华SUV
    {% else %}
        黄包车
    {% endif %}

    if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。

    (3) with标签

    使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

    例如:

    注意等号左右不要加空格。

    {% with total=business.employees.count %}
        {{ total }} <!--只能在with语句体内用-->
    {% endwith %}

    {% with business.employees.count as total %}
        {{ total }}
    {% endwith %}

    使用标签的注意事项

    1. Django的模板语言不支持连续判断,即不支持以下写法:

    {% if a > b > c %}
    ...
    {% endif %}

    Django的模板语言中属性的优先级大于方法(了解)

    def xx(request):
        d = {"a": 1, "b": 2, "c": 3, "items": "100"}
        return render(request, "xx.html", {"data": d})

    如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:

    {{ data.items }}

    默认会取d的items key的值。

    自定义标签和过滤器

    自定义过滤器

    注意:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    1、在app中创建templatetags文件夹(文件夹名只能是templatetags)

    2、在templatetags文件夹中创建任意 .py 文件,如:mytag.py

    3、在mytag.py文件中写上如下内容

    from django import template
    
    register = template.Library() #制作注册器,名字必须叫register
    
    #过滤最多两个参数
    @register.filter #注册过滤器,需要两个参数的
    def add(v1, v2):  #v1表示管道符前面的,v2表示冒号后面的参数
        print(v1,v2) #100 50
        return v1 + v2
    
    @register.filter #注册过滤器,需要一个参数的
    def xxx(v1):  #v1表示管道符前面的
        print(v1) 
        return 'xxx'

    4、使用,在html文件中写上如下内容

    {% load mytag %}  <!-- 首先通过load来加载一下mytag文件,不一定放在文件的开头,但是一定要放在使用过滤器的前面先进行引用 -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    <h1>base页面</h1>
      <!--{% load mytag %} 放这里也是可以的-->  
    <div>
        {{ num|add:50}}  <!-- 使用过滤器,和django内置过滤器用法一样,这里生成的是add函数的返回值 -->
    </div>
    <div>
        {{ num|xxx }}
    </div>
    <!--{% load mytag %} 放这里不行-->  
    
    </body>
    
    </html>

    自定义标签

    过程:

    1、在app中创建templatetags文件夹(文件夹名只能是templatetags)

    2、在templatetags文件夹中创建任意 .py 文件,如:mytag.py

    3、在mytag.py文件中写上如下内容

    from django import template
    
    register = template.Library() #制作注册器,名字必须叫register
    
    @register.simple_tag
    def atag(v1,v2): #没有参数个数限制
        print(v1,v2)
        return v1 + v2

    4、使用,在html文件中写上如下内容

    {#{% load mytag %}#}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    <h1>base页面</h1>
    {% load mytag %}
    
    <div>
        {% atag 'a' 'b' %}  <!-- 注意,是{%%} 来包裹使用,先是标签名称然后空格写参数,参数之间也是空格分隔的 -->
    </div>
    
    </body>
    
    </html>

    模板继承

    将一些页面公共的部分,可以抽离出来单独做成一个html页面,使用这些公用部分的其他html文件,只需要继承一下它就可以了,具体使用流程如下:

    1 创建公用模板,比如内容如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            body{
                padding: 0;
                margin: 0;
            }
            {% block css %}
            .nav{
                height: 60px;
                background-color: green;
            }
            {% endblock %}
            .nav a{
                color:white;
                text-decoration: none;
            }
            .left-menu{
                width: 30%;
                background-color: rgba(0,0,0,0.5);
                float:left;
            }
            .menu .menu-title{
                text-align: center;
            }
            .main{
                float: right;
                width: 65%;
                height: 300px;
                border: 1px solid red;
            }
        </style>
    </head>
    <body>
    
    <div class="nav">
        <a href="/xx1/">首页</a>
        <a href="/person/">个人中心</a>
        <a href="/detail/">详情页</a>
    </div>
    <div class="left-menu">
        <div class="menu">
            <div class="menu-title">菜单1</div>
            <div class="menu-body">
                <div class="item">包子</div>
                <div class="item">馒头</div>
                <div class="item">凉皮</div>
                <div class="item">面条</div>
            </div>
            <div class="menu-title">菜单2</div>
            <div class="menu-body">
                <div class="item">排骨藕汤</div>
                <div class="item">粉蒸肉</div>
                <div class="item">腊鱼块</div>
                <div class="item">灌肠</div>
            </div>
        </div>
    </div>
    <div class="main">
        {% block content %}
        公共页面
        {% endblock %}
    </div>
    
    </body>
    {% block js %}
        
    {% endblock %}
    
    </html>

    2 将来如果说继承公用模板的html文件中需要修改公用模板中的一些内容,那么需要在公用模板中预留一些钩子,钩子的写法如下

    {% block content %}  #block 后面的块名称随便起
    公共页面
    {% endblock %}
    #也可以这样写 {% endblock content %}  #endblock指定名称

    3 继承公用模板需要在html文件中写如下内容:

    {% extends 'xx.html' %}  <!-- 需要先继承一下公用模板,写法就是extends '公用模板文件名称',注意,必须写在第一行 -->
    
    {% block css %}
    .nav{
        height: 60px;
        background-color: pink;
    }
    {% endblock %}
    
    {% block content %}
        <h1>首页</h1>
    {% endblock %}

    4 在使用公用模板的其他html文件中,如果需要更改公用模板里面的内容,只需要在html文件中写上相同的钩子,钩子里面写上自定义的内容,写法如下

    {% block css %}
    .nav{
        height: 60px;
        background-color: pink;
    }
    {% endblock %}
    
    {% block content %}
        <h1>首页</h1>
    {% endblock %}

    注意事项:

    • 如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作,模板渲染的时候django都不知道你在干啥。

    • 在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。

    • 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。

    • {{ block super }}的使用,在子模板中也展示出父模板原来钩子中的内容

    {% block content %}
    
        <h1>首页</h1>
        {{ block.super }}
    {% endblock %}

    为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:

    {% block content %}
    ...
    {% endblock content %}  

    在大型模版中,这个方法帮你清楚的看到哪一个  {% block %} 标签被关闭了。

     

    不能在一个模版中定义多个相同名字的 block 标签。

    #两个block都叫content,这种写法是不对的
    {% block content %}
    
        <h1>首页</h1>
        {{ block.super }}
    {% endblock %}
    {% block content %}
    
        <h1>首页</h1>
        {{ block.super }}
    {% endblock %}

     

     

  • 相关阅读:
    processon--工作中画业务流程图很好的网站,欢迎推荐
    项目中关于RPC 和rocketMQ使用场景的感受
    如何永久激活(破解) IntelliJ IDEA 2018.2
    js生成二维码
    序列化反序列化
    bootstrap-treeview分级展示列表树的实现
    关于redis分布式锁实现原理
    LocalDate
    html css javascript mysql php学习总结
    JQuery中$.ajax()方法参数详解
  • 原文地址:https://www.cnblogs.com/fdsimin/p/13307159.html
Copyright © 2020-2023  润新知