• Django04-模板系统Template


    一、模板支持的语法

    Django模板中只需要记两种特殊符号:

    {{ }}表示变量,在模板渲染的时候替换成值
    {% %}表示逻辑相关的操作。

    二、 变量(使用双大括号来引用变量)

    1、语法格式:{{var_name}}

    变量名由字母数字和下划线组成。

    例子

    urls.py文件指定url和views中的函数对应关系
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^time/$', views.localtime),
    ]
    
    views.py文件中编写函数,指定页面并传递字典参数
    from django.shortcuts import render, HttpResponse
    import datetime
    
    def localtime(request):
        time = datetime.datetime.now()
        return render(request, 'time.html', {'time':time})
    
    time.html编写html页面,通过双大括号接收字典参数
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {{ time }}
    </body>
    </html>
    
    访问http://127.0.0.1:8000/time/显示时间
    Feb. 15, 2019, 1:53 p.m.

    locals()可以将函数中所有的变量全部传递给模板,可能会造成传递了多余的参数。

    def test(request):
        a = 1
        b = 2
        c = 3
        return render(request, 'test.html', locals())
    
    #可以将a,b,c全部传递给模板

    2、 深度变量的查找(万能的句点号)

    上面例子中,我们传递的参数值主要是字符串,然而模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。在Django模板中遍历复杂数据结构的关键是句点字符 (.)。

    urls.py和views.py中的代码不变,time.html文件修改如下:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p>日期:{{ time.year }}年{{ time.month }}月{{ time.day }}日</p>
    </body>
    </html>
    
    访问网页显示如下:
    日期:2019年2月15日

    例子2:循环显示列表中的内容

    views.py
    def people(request):
        people = [
            {'name':'tom', 'age':20},
            {'name':'mike', 'age':21},
            {'name':'jack', 'age':22},
        ]
        return render(request, 'people.html', {'people':people})
    
    people.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            table{
                border: 1px solid black;
                border-spacing: 0;
                 300px;
            }
            table td{
                border:1px solid;
                text-align: center;
                padding: 10px 0px;
            }
        </style>
    </head>
    <body>
    <table>
        <tr>
            <td>ID</td>
            <td>姓名</td>
            <td>年龄</td>
        </tr>
        {% for people in people %}
            <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ people.name }}</td>
            <td>{{ people.age }}</td>
            </tr>
        {% endfor %}
    </table>
    </body>
    </html>
    
    访问页面结果显示:

    例子3:

    def template_test(request):
        l = [11, 22, 33]
        d = {"name": "alex"}
    
        class Person(object):
            def __init__(self, name, age):
                self.name = name
                self.age = age
    
            def dream(self):
                return "{} is dream...".format(self.name)
    
        Alex = Person(name="Alex", age=34)
        Egon = Person(name="Egon", age=9000)
        Eva_J = Person(name="Eva_J", age=18)
    
        person_list = [Alex, Egon, Eva_J]
        return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})

    模板中支持的写法:

    {# 取l中的第一个参数 #}
    {{ l.0 }}
    {# 取字典中key的值 #}
    {{ d.name }}
    {# 取对象的name属性 #}
    {{ person_list.0.name }}
    {# .操作只能调用不带参数的方法 #}
    {{ person_list.0.dream }}

    注:当模板系统遇到一个(.)时,会按照如下的顺序去查询:

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

    3 变量的过滤器(filter)的使用

    语法格式:{{obj|filter:param}}
    '|'左右没有空格

    value1 = 'abc'
    value2 = 11
    value3 = []
    value4 = None
    value5 = 'name is tom and age is 20'
    value6 = '姓名小明年龄20'
    value7 = '<a herf="#">跳转</a>'
    value8 = 'https://www.baidu.com/?a=1&b=2'
    
    <p>日期:{{ time.year}}年{{ time.month}}月{{ time.day}}日</p>
    #日期:2019年2月15日
    
    格式化日期
    <p>日期:{{ time|date:"Y年m月d日" }}</p>
    #日期:2019年02月15日
    
    <p>日期:{{ time|date:"Y-m" }}</p>
    #日期:2019-02
    
    字母大写
    <p>{{ value1|upper }}</p>
    #ABC
    
    变量值加2,如果变量是float则只显示整数部分,如果要减2,可以写成-2
    <p>{{ value2|add:2 }}</p>
    #13
    
    首字母大写
    <p>{{ value1|capfirst }}</p>
    #Abc
    
    title标题
    {{ value|title }}
    
    ljust左对齐
    {{ value|ljust:"10" }}
    
    rjust右对齐
    {{ value|rjust:"10" }}
    
    center居中
    {{ value|center:"15" }}
    
    join使用字符串拼接列表。同python的str.join(list)。
    {{ value |join:" // " }}
    
    切除掉指定字符串,可以用于切掉空格
    <p>{{ value1 | cut:'b' }}</p>
    #ac
    
    如果值为false,则显示默认值
    <p>{{ value3 | default:'值是假或空' }}</p>
    #值是假或空
    
    如果值为None,则显示默认值
    <p>{{ value4 | default_if_none:'值是None' }}</p>
    #值是None
    
    只显示前3个单词,以空格为分隔,后面的内容显示为...
    <p>{{ value5 | truncatewords:3 }}</p>
    #name is tom ...
    
    只显示前10个字符,后面的内容显示为...,而且这10个字符包括3个点,也就是只显示前7个字符
    <p>{{ vlaue6 | truncatechars:7 }}</p>
    
    <p>{{ value7 }}</p>
    #<a herf="#">跳转</a>
    
    <p>去掉自动转义:
      {% autoescape off %}
        {{ value7 }}
    {% endautoescape %}
    </p>
    #跳转
    
    <p>{{ value7 | safe }}</p>
    #跳转
    
    <p>{{ value7 | striptags }}</p>
    #跳转
    
    转成KB格式
    <p>{{ value2 | filesizeformat }}</p>
    #11 bytes
    
    <p>第1个字符:{{ value1 | first }}</p>
    #a
    
    <p>最后1个字符:{{ value1 | last }}</p>
    #c
    
    <p>显示长度:{{ value1 | length }}</p>
    #3
    
    <p>切片:{{ value1 | slice:'1::' }}</p>
    #bc
    
    <p>{{ value8 | urlencode }}</p>
    #https%3A//www.baidu.com/%3Fa%3D1%26b%3D2

    三、 标签(tag)的使用(使用大括号和百分号的组合来表示tag)

    语法格式: {% tags %}

    1、 if elif和else的使用

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

    {% if %}标签判断一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容。

    {% if num >= 100 %}
        {% if num > 200 %}
            <p>num大于200</p>
        {% else %}
            <p>num大于100小于200</p>
        {% endif %}
    
    {% elif num < 100%}
        <p>num小于100</p>
    
    {% else %}
        <p>num等于100</p>
    
    {% endif %}

    {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
    {% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:{% if obj1 and obj2 or obj3 %}

    2、 for的使用

    {% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容。

    <ul>
    {% for obj in list %}
        <li>{{ obj.name }}</li>
    {% endfor %}
    </ul>

    在标签里添加reversed来反序循环列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

    {% for %}标签可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}

    系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息

    1)、forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {% for item in todo_list %}
    <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}

    2)、forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0

    3)、forloop.revcounter 倒序排序,最小为1

    4)、forloop.revcounter0 倒序排序,最小为0

    5)、forloop.first当第一次循环时值为True,在特别情况下很有用:

    {% for object in objects %} 
    {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} 
    {{ object }} 
    </li> 
    {% endfor %} 

    6)、forloop.last 当前循环是不是最后一次循环(布尔值)

    7)、forloop.parentloop 本层循环的外层循环

    # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
    # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
    # 在其他非循环的地方,你的forloop变量仍然可用

    3、 empty的使用

    {% empty %}不需要写{% endempty %}

    <ul>
    {% for user in user_list %}
        <li>{{ user.name }}</li>
    {% empty %}
        <li>空空如也</li>
    {% endfor %}
    </ul>

    4、变量值乘除

    {% widthratio 数 分母 分子%}
    
    {% widthratio 5 1 2%} 表示5乘以2
    {% widthratio 10 2 1%} 表示10除以2

    5、divisibleby value除以后面的参数,除尽为True,否则为False。可用于隔行变色

    {% if value|divisibleby:"2" %}
    Even!
    {% else %}
    Odd!
    {% else %}

    6、ifequal / ifnotequal

    在模板语言里比较两个值可以用ifequal和ifnotequal标签
    与 if 标签一样,ifequal 和 ifnotequal标签也支持else标签,但不支持elif,可以在else里面嵌套if语句。

    {# 如果 a1 == a2 则显示 #}
    {% ifequal a1 a2 %}
    <h1>equal!</h1>
    {% else %}
    <h1>not equal!</h1>
    {% endifequal %}

    首行显示红色

    {% for student in students %}
        {% ifequal forloop.count 1%}
            <li style="color:red">{{student.name}}</li>
        {% else%}
            <li>{{student.name}}</li>
        {% endifequal %}
    {% endfor %}

    7、 with

    定义一个中间变量,用更简单的变量名替代复杂的变量名

    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

    8、 csrf_token标签

    用于生成csrf_token的标签,用于防治跨站攻击验证。 其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

    csrf豁免还有一种方式,是在函数上添加一个csrf_exempt装饰器,来实现指定某个post不需要csrf校验

    @csrf_exempt
    def login(request):
        ...

    9、 url

    引用路由配置的地址别名

    <form action="{% url "bieming"%}" >
              {%csrf_token%}
              <input type="text">
              <input type="submit"value="提交">
    </form>

    #如果使用get请示,可以在url后面添加?get参数

      <a herf="{% url 'app:user' %}?id={{ user_id }}"></a>

      #如果使用post请示,可以在别名后面添加post参数

      <a herf="{% url 'app:user' user_id %}"></a>

    10、 verbatim

    禁止render

    {% verbatim %}
    {{ hello }}
    {% endverbatim %}

    11、 注释

    • 这种在前端页面的代码中是可以看到注释的,不推荐使用
    <!--
    注释内容abc
    -->
    • 2、单行注释
    {# 看不到我! #}
    • 多行注释
    {% comment %}
    看不到我!
    看不到我!
    看不到我!
    {% endcomment %}

    这两种在前端代码中是看不见的,推荐使用

    12、 注意事项

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

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

    2). 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的值100。

    四、extend模板继承

    到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用Django模板系统来创建整个HTML页面。 这就带来一个常见的Web开发问题:在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?Django解决此类问题的首选方法是使用一种优雅的策略—— 模板继承 。

    本质上,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

    1、定义基础模板

    该模板将由子模板所继承,以下是基础模板base.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    </head>
    <body>
    <h1>欢迎访问</h1>
    {% block content %}{% endblock %}
    
    {% block footer %}
    <hr>
    <p>Thanks for visit my site</p>
    {% endblock %}
    </body>
    </html>

    使用模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 每个{% block %}标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。

    2、继承母板

    现在我们已经有了一个基本模板,我们可以通过多个子模板模板来继承它,子页面中在页面最上方使用{% extends 'base.html' %}语法来继承母板

    user.html
    {% extends "base.html" %}
    {% block title %}user{% endblock %}
    {% block content %}
    <p>用户管理界面</p>
    {% endblock %}
    
    host.html
    {% extends "base.html" %}
    {% block title %}host{% endblock %}
    {% block content %}
    <p>主机管理界面</p>
    {% endblock %}

    如果想进行站点级的设计修改,仅需修改 base.html ,所有其它模板会立即反映出所作修改。

    3、块(block)

    通过在母板中使用{% block xxx %}来定义"块"。
    在子页面中通过定义母板中的block名来对应替换母板中相应的内容。

    {% block page-main %}
    <p>世情薄</p>
    <p>人情恶</p>
    <p>雨送黄昏花易落</p>
    {% endblock %}

    4、组件
    可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

    {% include 'navbar.html' %}

    以下是其工作方式:

    1、在加载user.html和host.html模板时,模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。
    2、模板引擎立即装载其父模板,即base.html。此时,base.html中的三个{% block %}标签中的内容将使用子模板的内容替换这些block。
    3、由于子模板并没有定义footer块,模板系统将使用在父模板中定义的值。

    使用继承的一种常见方式是下面的三层法:

    <1> 创建base.html模板,在其中定义站点的主要外观,这些都是不常修改甚至从不修改的部分。
    <2> 为网站的每个区域创建base_SECTION.html模板(例如, base_photos.html 和 base_form.html )。这些模板对base.html进行拓展,并包含区域特定的风格与设计。
    <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。
    这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。

    以下是使用模板继承的一些诀窍:

    <1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。
    <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越多越好。
    <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。
    <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。

    五、静态文件相关

    settings.py文件:

    STATIC_URL = '/static/'
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'statics'),
    ]

    将images文件夹、mytest.js等静态文件放到创建的statics文件夹中

    模板文件:

    {% load static %}
    <img src="{% static 'images/hi.jpg' %}" alt="Hi!" />
    
    引用JS文件时使用:
    {% load static %}
    <script src="{% static 'mytest.js' %}"></script>
    
    某个文件多处被用到可以存为一个变量
    {% load static %}
    {% static "images/hi.jpg" as myphoto %}
    <img src="{{ myphoto }}"></img>
  • 相关阅读:
    Arduino nano的bootloader文件烧录
    arduino通信问题的学习与解决
    arduino中的serial .available()和serial.read()
    arduino 通过串口接收string,int类型数据
    Arduino读取串口数据并进行字符串分割
    Arduino 的读串口与写串口
    代理模式
    策略模式
    python中的深拷贝
    Python中的三个特殊函数
  • 原文地址:https://www.cnblogs.com/dxnui119/p/10434556.html
Copyright © 2020-2023  润新知