zoukankan      html  css  js  c++  java
  • 5. Flask模板

    一、Jinja2模板引擎

    1. 定义

    ​ 视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。本节学到的模板,它的作用即是承担视图函数的另一个作用,即返回响应内容。

    ​ 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取。使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”。Flask是使用 Jinja2 这个模板引擎来渲染模板。

    2. 好处

    • 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
    • 而模板则取到视图函数的数据结果进行展示(视图展示方面)
    • 代码结构清晰,耦合度低

    3. 模板引擎的两个概念

    ​ Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名。

    4. 渲染模板函数

    • Flask提供的 render_template 函数封装了该模板引擎
    • render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值。

    二、Flask模板使用

    1. 变量类

    {{}} 来表示变量名,这种 {{}} 语法叫做变量代码块
    
    <h1>{{ post.title }}</h1>
    

    2. 控制类

    - if/else if /else / endif
    - for / endfor
    
    {% if comments | length > 0 %}
        There are {{ comments | length }} comments
    {% else %}
        There are no comments
    {% endif %}
    
    {% for post in posts %}
        <div>
            <h1>{{ post.title }}</h1>
            <p>{{ post.text | safe }}</p>
        </div>
    {% endfor %}
    
    模拟continue功能
    
    {% for post in posts if post.text %}
        <div>
            <h1>{{ post.title }}</h1>
            <p>{{ post.text | safe }}</p>
        </div>
    {% endfor %}
    
    用 {%%} 定义的控制代码块,可以实现一些语言层次的功能,比如循环或者if语句
    
    {% if user %}
        {{ user }}
    {% else %}
       
    <ul>
        {% for index in indexs %}
        <li> {{ index }} </li>
        {% endfor %}
    </ul>
    

    3. 注释类

    使用 {# #} 进行注释,注释的内容不会在html中被渲染出来
    
    {# {{ name }} #}
    

    4. 模板使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>{{ title | reverse | upper }}</h1>
    
    <ul>
        {% for item in my_list %}
            <li>{{ item.id }}----{{ item.value }}</li>
        {% endfor %}
    </ul>
    
    {% for item in my_list %}
        {% if loop.index==1 %}
            <li>{{ loop.index }}--{{ item.get('value') }}</li>
        {% elif loop.index==2 %}
            <li>{{ loop.index }}--{{ item.get('value') }}</li>
        {% elif loop.index==3 %}
            <li>{{ loop.index }}--{{ item.get('value') }}</li>
        {% else %}
            <li>{{ loop.index }}--{{ item.get('value') }}</li>
        {% endif %}
    {% endfor %}
        
    </body>
    </html>
    

    三、过滤器

    1. 定义

    ​ 过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。

    1. 链式调用
    
    {{ "hello world" | reverse | upper }}
    

    2. 常见内建过滤器

    (1)字符串操作
    safe:禁用转义
    
    <p>{{ '<em>hello</em>' | safe }}</p>
    
    capitalize:把变量值的首字母转成大写,其余字母转小写
    
    <p>{{ 'hello' | capitalize }}</p>
    
    lower:把值转成小写
    
    <p>{{ 'HELLO' | lower }}</p>
    
    upper:把值转成大写
    
    <p>{{ 'hello' | upper }}</p>
    
    title:把值中的每个单词的首字母都转成大写
    
    <p>{{ 'hello' | title }}</p>
    
    reverse:字符串反转
    
    <p>{{ 'olleh' | reverse }}</p>
    
    format:格式化输出
    
    <p>{{ '%s is %d' | format('name',17) }}</p>
    
    striptags:渲染之前把值中所有的HTML标签都删掉
    
    <p>{{ '<em>hello</em>' | striptags }}</p>
    
    truncate: 字符串截断
    
    <p>{{ 'hello every one' | truncate(9) }}</p>
    
    (2)列表操作
    first:取第一个元素
    
    <p>{{ [1,2,3,4,5,6] | first }}</p>
    
    last:取最后一个元素
    
    <p>{{ [1,2,3,4,5,6] | last }}</p>
    
    length:获取列表长度
    
    <p>{{ [1,2,3,4,5,6] | length }}</p>
    
    sum:列表求和
    
    <p>{{ [1,2,3,4,5,6] | sum }}</p>
    
    sort:列表排序
    
    <p>{{ [6,2,3,1,5,4] | sort }}</p>
    
    (3)语句块操作
    {% filter upper %}
        #一大堆文字#
    {% endfilter %}
    

    3. 自定义构造器

    from flask import Flask
    from flask import render_template
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def index():
        list1 = list(range(10))
        my_list = [{"id": 1, "value": "我爱工作"},
                   {"id": 2, "value": "工作使人快乐"},
                   {"id": 3, "value": "沉迷于工作无法自拔"},
                   {"id": 4, "value": "日渐消瘦"},
                   {"id": 5, "value": "以梦为马,越骑越傻"}]
        return render_template(
            # 渲染模板语言
            'index.html',
            title='hello world',
            list2=list1,
            my_list=my_list
        )
    
    
    # step1 定义过滤器
    def do_listreverse(li):
        temp_li = list(li)
        temp_li.reverse()
        return temp_li
    
    
    # step2 添加自定义过滤器
    app.add_template_filter(do_listreverse, 'listreverse')
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    四、代码复用

    1. 宏 - 类似Python函数

    1. 创建
    {% macro 标签名(key=value)%} {% end macro %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!-- step1 宏导入 import filename as xx-->
    {% import 'd8_macro2.html' as fun %}
    <!-- step2 宏调用 类似于python函数调用 -->
    {{ fun.input('button','zhuce') }}
    </body>
    </html>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!-- step1 宏导入 import filename as xx-->
    {% import 'd8_macro2.html' as fun %}
    <!-- step2 宏调用 类似于python函数调用 -->
    {{ fun.input('button','zhuce') }}
    </body>
    </html>
    

    2. 继承

    1. 关键字 - block extends;继承:常常用于上下部分不做修改的网址
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>top123 {{ title }}</h1><br>
    
    <!-- 预留空间 给继承的html -->
    {% block body %}{% endblock %}
    
    <br><h1>bottom</h1>
    </body>
    </html>
    
    {% extends 'd1_base.html' %}
    
    {% block body %}
    <h2>detail</h2>
    {% endblock %}
    

    3. 包含

    ​ 包含: 将一个模板加载到另一个模板里面种

    <h1>这是一个多页面共同的内容</h1>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!-- 特殊的自定义 函数 -->
    <h1>{{ request.url }}</h1>
    <h2>{{ g.title }}</h2>
    index
    <br>
    <!-- include 调用html文件 -->
    {% include 'd2_include.html' %}
    <hr>
    <!-- 已经内置的特殊变量 -->
    {{ url_for('detail') }}<br>
    <a href="{{ url_for('detail') }}">详细页面</a>
    </body>
    </html>
    

    4. 总结

    • 宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
    • 继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
    • 宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
    • 包含(include)是直接将目标模板文件整个渲染出来。

    五、CORS

    1. 描述

     a. 访问A时进行了登录
     b. A进行了状态保持
     c. 访问网站B
     d. 返回攻击代码
     e. 向网站A发起请求 在用户未意识到的情况下
    

    2. 防止

    1.修改操作 由get操作 改为 post方式
    	数据修改 get -> post
    	跨网站 借用用户信息 访问目标网站
    2.口令验证 随机产生 
    	随机产生一个口令 拿这个口令做对比
    	安装包 pip install flask-wtf
    

    3. 开发人员防止

    1.设置加密字段
    	app.secret_key('fad')
    2.引入类
    	from flask_wtf.csrf import CRSFProtect
    3.创建对象
    	CRSFProtect(app)
    4.在模板的form中生成一个随机的口令值
    	<input type="hidden" name="crsf_token" value="{{csrf_token()}}">
    

    4. 代码实现原理

    注册了请求勾子before_request这个函数会在视图函数前执行,进行口令验证。如何验证?接收表单传递的口令session的口令对比。
    
    CRSFProtect === init === init_app ==== crsf_protect === protect ===saft_str_cmp(session[filed_name], token)
    
    session中的值是什么时候写? 在调用csrf_token()函数时
    
    from flask import Flask, render_template
    
    app = Flask(__name__)
    # 1 设置加密字符串
    app.secret_key = 'python'
    # 2. 引入类
    from flask_wtf.csrf import CSRFProtect
    # 3. 创建对象
    CSRFProtect(app)
    
    @app.route("/")
    def index():
        return render_template('d3_index.html')
    
    
    @app.route("/detail", methods=['POST'])
    def detail():
        return 'ok'
    
    
    if __name__ == '__main__':
        app.run()
    
  • 相关阅读:
    bzoj1415 NOI2005聪聪和可可
    Tyvj1952 Easy
    poj2096 Collecting Bugs
    COGS 1489玩纸牌
    COGS1487 麻球繁衍
    cf 261B.Maxim and Restaurant
    cf 223B.Two Strings
    cf 609E.Minimum spanning tree for each edge
    cf 187B.AlgoRace
    cf 760B.Frodo and pillows
  • 原文地址:https://www.cnblogs.com/hq82/p/12638092.html
Copyright © 2011-2022 走看看