• 【Flask】02-模板


    工欲善其事,必先利其器。

    1. 模板使用

    Flask的模板功能是基于Jinja2模板引擎实现的。接下来我们创建一个新的Flask运行文件,代码如下:

    from flask import Flask, render_template
    app = Flask(__name__)
    @app.route("/")
    def index():
        # return render_template('index.html', username="ydy", age=18)
        context = {
            "username": "ydongy",
            "age": 23,
            "gender": "male",
            "info": {
                "phone": "17xxxxxxxx",
                "email": "example@example.com"
            },
            "nums": [1, 2, 3, 4]
        }
        return render_template('index.html', **context)
    

    代码中可以发现render_template是主要用来渲染模板,同时可以传入多个关键字参数,也可以对一个字典进行解包的形式传递参数。

    2. 模板变量

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    <h1>index</h1>
    {{ username }}
    {{ age }}
    {{ gender }}
    {{ info.phone }}
    {{ info["phone"] }}
    {{ info.email }}
    {{ info.aaa }}
    <a href="{{ url_for('login',ref="/") }}">登陆</a>
    </body>
    </html>
    
    • {{变量名}}:获取模板传递过来的关键字参数,名称需要一致
    • {{变量名.键}}:接受一个字典参数,可以通过键获取值
    • {{变量名[键]}}:字典值的获取
    • {{url_for('视图名称',ref="当前url路径")}}:这里的url_for和视图中的用法一致,用于反转获取url地址,ref用于跳转之后指定是从那个页面跳转,如下的例子:
    http://127.0.0.1:5000/login/?ref=%2F
    

    3. 过滤器

    有时候我们想要在模版中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模版中,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。

    基本语法

    {{ variable|过滤器名字 }},使用管道符号 | 进行组合。
    

    3.1 default过滤器

    1. {{ value|default('默认值') }}
    2. {{ value|default('默认值',boolean=True) }}
    
    示例:
    {{ b | default('不存在',boolean=True) }}
    {{ b or '不存在' }}
    
    1. 表示当value不存在的时候,那么就会使用default过滤器提供的默认值
    2. bollean=True:表示如果想要判断一个值是否为False(例如:None、空字符串、空列表、空字典等),也可以使用or来替代。

    3.2 转义过滤器

    @app.route("/filter/")
    def my_filter():
        context = {
            "signature": '<script>alert("hello")</script>',
            "create_time": datetime.now()
        }
        return render_template('posts/filter.html', **context)
    

    上面代码可以发现,传递的变量含有标准的html标签,如果想要获取这个字符串渲染成html标签的话就需要关闭自动转义,如以下的模板语法。

    1. safe过滤器:可以关闭一个字符串的自动转义。
    2. escape过滤器:对某一个字符串进行转义。
    3. autoescape标签,可以对他里面的代码块关闭或开启自动转义。
    示例:
    {#关闭自动转义渲染成html标签#}
    <p>个性签名:{{ signature | safe }}</p>
    
    {#开启转义阻止渲染成html标签#}
    <p>个性签名:{{ signature | escape  }}</p>
    
    {#关闭自动转义#}
    {% autoescape off %}
      ......代码块
    {% endautoescape %}
    

    3.3 常用过滤器

    1. first(value):返回一个序列的第一个元素。names|first。
    2. format(value,*arags,**kwargs):格式化字符串。例如以下代码:
    {{ "%s" - "%s"|format('Hello?',"Foo!") }}
    
    >>>Helloo? - Foo!
    
    1. last(value):返回一个序列的最后一个元素。示例:names|last。
    2. length(value):返回一个序列或者字典的长度。示例:names|length
    3. join(value,d=u''):将一个序列用d这个参数的值拼接成字符串。
    4. safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe
    5. int(value):将值转换为int类型。
    6. float(value):将值转换为float类型。
    7. lower(value):将字符串转换为小写。
    8. upper(value):将字符串转换为小写。
    9. replace(value,old,new): 替换将old替换为new的字符串。
    10. truncate(value,length=255,killwords=False):截取length长度的字符串。
    11. striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
    12. trim:截取字符串前面和后面的空白字符。
    13. string(value):将变量转换成字符串。
    14. wordcount(s):计算一个长字符串中单词的个数。

    3.4 自定义模板过滤器

    过滤器本质上就是一个函数。如果在模版中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器这个函数,然后函数的返回值会作为这个过滤器的返回值。需要使用到一个装饰器:@app.template_filter('cut')

    # 自定义过滤器,把hello替换为空字符串
    @app.template_filter('cut')
    def cut(value):
        value = value.replace("hello",'')
        return value
    
    <p>{{ article|cut }}</p>
    

    4. 判断语句

    {% if statement %}
         ......代码块
    {% endif %}
    

    判断语句和python中的判断语句一致,也可以使用>,<,<=,>=,==,!=来进行判断,也可以通过and,or,not,()来进行逻辑合并操作。

    5. for循环

    {% for x in range(1,10) %}
         ......代码块
    {% endfor %}
    

    循环语句和python中同样类似,采用in来遍历所有的序列以及迭代器,但是注意jinja2中的循环没有breakcontinue如果你启用了jinja2.ext.loopcontrols扩展的话,你还可以在循环中使用{% break %}{% continue %}来控制循环执行。

    Jinja2的循环内置变量主要有以下几个:

    变量 内容
    loop.index 循环迭代计数(从1开始)
    loop.index0 循环迭代计数(从0开始)
    loop.revindex 循环迭代倒序计数(从len开始,到1结束)
    loop.revindex0 循环迭代倒序计数(从len-1开始,到0结束)
    loop.first 是否为循环的第一个元素
    loop.last 是否为循环的最后一个元素
    loop.length 循环序列中元素的个数
    loop.cycle 在给定的序列中轮循,如上例在”odd”和”even”两个值间轮循
    loop.depth 当前循环在递归中的层级(从1开始)
    loop.depth0 当前循环在递归中的层级(从0开始)

    循环中使用if

    {% for y in range(1,10) if y <= 5 %}
           ......代码块        
    {% endfor %}
    

    6. 宏

    模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量。

    6.1 定义宏

    {% macro input(name="",value="",type="text") %}
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    {% endmacro %}
    

    6.2 使用宏

    • 直接导入宏内定义的函数
    {% from "posts/macros.html" import input %}
    
    {{ input(value="提交",type="submit") }}
    

    上面代码定义宏就相当于创建一个input函数,参数包括:name,value,type,使用宏就相当于调用函数

    • 导入宏,通过宏调用
    {{ macros.input(value="提交",type="submit") }}
    

    6.3 导入宏

    {#引入宏#}
    {% from "posts/macros.html" import input %}
    {% import"posts/macros.html" as macros %}
    
    {#把当前变量传入到宏#}
    {% import"posts/macros.html" as macros with context %}
    

    如果想要在导入宏的时候,就把当前模版的一些参数传给宏所在的模版,那么就应该在导入的时候使用with context

    6. include标签

    这个标签相当于是直接将指定的模版中的代码复制粘贴到当前位置。

    例如:下面这一部分代码是公共页脚代码templates/posts/footer.html

    <footer>
        底部
    </footer>
    

    从当前页面引入页脚代码

    {#使用公共模板#}
    <ul>
        <div class="content">
            中间
        </div>
        {% include "posts/footer.html" %} {#相当于把代码复制在此处#}
    </ul>
    

    7. set和with语句

    在模版中,可以使用set语句来定义变量。示例如下:

    {% set username='zhangsan' %}
    <p>用户名:{{ username }}</p>
    

    一旦定义了这个变量,那么在后面的代码中,都可以使用这个变量,就类似于Python的变量定义是一样的。

    with语句定义的变量,只能在with语句块中使用,超过了这个代码块,就不能再使用了。示例代码如下:

    • 方式一
    {% with classroom = '一班' %}
    <p>班级:{{ classroom }}</p>
    {% endwith %}
    
    • 方式二
    {% with %}
        {% set age=18 %}
        <p>age: {{ age }}</p>
    {% endwith %}
    

    8. 模板继承

    模版继承可以把一些公用的代码单独抽取出来放到一个父模板中。以后子模板直接继承就可以使用了。提高代码的复用性

    使用extends语句,来指明继承的父模板。父模板的路径,也是相对于templates文件夹下的绝对路径

    {% extends "base.html" %}
    

    如下定义一个父模板templates/posts/base.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            {% block title %}
    
            {% endblock %}
        </title>
    </head>
    <body>
    我是父模板里面的代码
    {% block body_block %}
        我是父模板block中的代码
    {% endblock %}
    </body>
    </html>
    

    父模板代码中定义了两个block语句块,相当于预留块,只要在子模板中重写block语句块就可以实现不同的代码。

    {# 导入父模板 #}
    {% extends "posts/base.html" %}
    
    {# 重写title #}
    {% block title %}
        sub
    {% endblock %}
    
    {% block body_block %}
    {# 调用父模板block中的代码,否则就被覆盖 #}
        {{ super() }}
    
    {# 调用另一个block中的内容 #}
        {{ self.title() }}
    
        我是子模板block的代码
    {% endblock %}
    

    更多参考:
    http://www.bjhee.com/flask-ad3.html
    https://dormousehole.readthedocs.io/en/latest/quickstart.html#

  • 相关阅读:
    WinForm 无边框窗体 拖动工作区移动窗体
    [CSS]火狐和IE对css样式解释的差异
    md类型文件迁移至Notion(img资源也可以上传)
    google推出notebook软件
    刚收到几个google analytics 邀请,有真正需要的我可以送给他一个
    最近用drupal做了一个CMS网站
    google adsense 又增加了Picasa的推介,我已加上
    googlepages空间的一个bug
    近段时间比较郁闷
    开复与学生面对面
  • 原文地址:https://www.cnblogs.com/ydongy/p/13157574.html
Copyright © 2020-2023  润新知