zoukankan      html  css  js  c++  java
  • flask(1.0)

    一. 关于KeyErrorIndexError

    1. KeyError
    dic = {"name": "王乃卉", "age": "19", "gender": "女"}
    print(dic["names"])
    
    # 执行结果:
    # KeyError: 'names'
    
    1. IndexError
    lst = ["a", "b", "c"]
    print(lst[3])
    
    # 执行结果:
    # IndexError: list index out of range
    

    二. Python三大主流框架对比

    • Django 主要特点是大而全,集成了很多组件(例如Models、Admin、Form等等), 不管你用得到用不到,反正它全都有,属于全能型框架,通常用于大型Web应用,由于内置组件足够强大所以使用Django开发可以一气呵成,优点是大而全,缺点也就暴露出来了,这么多的资源一次性全部加载,肯定会造成一部分的资源浪费

    • Tornado 主要特点是原生异步非阻塞,在IO密集型应用和多任务处理上占据绝对性的优势,属于专注型框架,通常用于API后端应用,游戏服务后台,其内部实现的异步非阻塞真是稳得一批,优点是异步,缺点是干净,连个Session都不支持;

    • Flask 主要特点小而轻,原生组件几乎为0,三方提供的组件(请参考Django)非常全面,属于短小精悍型框架,通常应用于小型应用和快速构建应用,其强大的三方库,足以支撑一个大型的Web应用,优点是精悍简单,缺点是稳定性较差,主要因为其组件都是第三方提供,要等第三方收到更新版本通知后才能更新,否则会出现一些兼容问题;

    三. flask基础

    1.安装flask

    pip install flask
    

    2.用flask写出的第一个页面

    from flask import Flask  # 导入Flask类
    
    app = Flask(__name__)  # 实例化Flask对象
    
    
    @app.route("/")  # app对象中的route装饰器
    def index():  # 视图函数
        return "Hello Flask"
    
    
    if __name__ == '__main__':
        app.run()  # 启动flask web服务
    

    启动该程序, 控制台和浏览器显示如下:

    3.Flask的Response"三剑客"

    我们知道django中的Response有3种形式(HttpResponseredirectrender),对比django,来看一下flask中有哪些返回形式。

    (1)返回HttpResponse对象

    @app.route("/")
    def index():
        return "Hello Flask"    # 相当于django中的HttpResponse
    

    (2)重定向redirect

    from flask import redirect	# 导入flask中的redirect
    
    @app.route("/home")
    def home():
        return redirect("/login")	# 重定向至"/login"路径
    

    (3)返回模板页面render_template

    from flask import render_template	# 导入flask中的render_template
    
    @app.route("/login")
    def login():
        return render_template("login.html")	# 渲染模板login.html
    

    新建一个templates文件夹, 在该文件夹中创建login.html文件:

    4. flask之jsonify,send_file

    (1)jsonify返回标准的json字符串

    from flask import jsonify
    
    @app.route("/jsons")
    def jsons():
        dic = {"name":"wnaglihong"}
        return jsonify(dic)
    

    返回json字符串,并且会在响应头中加Content-Type:application/json,即告诉浏览器数据是json字符串,浏览器收到后会自动进行反序列化,而使用json.dumps()则不会加此响应头。

    (2)send_file打开文件并返回文件内容(自动识别文件格式)

    from flask import send_file
    
    @app.route("/flie")
    def file():
        return send_file("01.mp4")
    

    send_file自动识别文件类型,即在返回文件内容时加一个响应头Content-Type:文件类型

    5. flask中的request(公共变量)

    每个框架中都有处理请求的机制,但是每个框架的处理方式和机制是不同的,为了了解Flask的request中都有什么,我们先来写一个基于html+flask前后端交互的示例。

    html页面代码:

    <body>
    <form action="/login" method="post">
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="password" name="password">
        <br>
        <input type="submit" value="登录">
    </form>
    </body>
    

    flask代码:

    from flask import Flask, request, render_template
    
    app = Flask(__name__)
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            print(request.args.get("name"))	# 查看url中的参数
            print(request.args.to_dict())	# 获取url参数字典
            return render_template("login.html")
        else:
            print(request.form.get("password"))	# 获取form数据内容
            print(list(request.form.items()))	# 获取form数据内容
            print(request.values)	# 有大坑!!!!!!
            return "OK"
    
    if __name__ == "__main__":
        app.run(host="0.0.0.0", port=9527, debug=True)
    
    • request.method -- 获取请求方式

    • request.args -- 获取url中的参数

      • request.args.get()
      • request.args.to_dict()
    • request.form -- 获取客户端提交来的FormData数据

      • request.form.get()
      • request.form.to_dict()
    • request.json -- 请求头中含有Content-Type:application/json时, 数据会在request.json

    • request.data -- 如果提交时请求头中的Content-Type无法被识别,将请求体中的原始数据保存,bytes类型

    • request.files -- 序列化文件, 存储用save()方法,且可以通过filename获取文件名

      • my_file = request.files.get("my_file")
        my_file.save(my_file.filename)
        
    • request.values -- 只要是个参数都保存在其中,用于查看,不要使用to_dict(),键重复会覆盖

    • request.cookies -- 存在浏览器端的字符串也会一起带过来

    • request.headres -- 请求头中的信息

    • 杂项: 获取各种路径

      • request.path
      • request.url
      • request.base_url
      • request.host
      • request.host_url

    6. jinja2

    (1)简介

    同django的模板语法类似,flask使用的jinja2的语法,且同django的模板语法很类似,下面简单介绍一下使用方法,对比django的理解和记忆:

    后端数据如下:

    STUDENT = {
        'id':1, 'name': 'zhangsan', 'age':15, 'gender': 'male'
    }
    
    STU_LIST = [
        {'id':1, 'name': 'zhangsan', 'age':15, 'gender': 'male'},
        {'id':2, 'name': 'lisi', 'age':18, 'gender': 'female'},
        {'id':3, 'name': 'wangwu', 'age':25, 'gender': 'buzhidao'}
    ]
    
    STU_DICT = {
        1: {'name': 'zhangsan', 'age':15, 'gender': 'male'},
        2: {'name': 'lisi', 'age':18, 'gender': 'female'},
        3: {'name': 'wangwu', 'age':25, 'gender': 'buzhidao'}
    }
    
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route("/index")
    def index():
        return render_template("index.html", stu=STUDENT, stu_list=STU_LIST, stu_dict=STU_DICT)
    

    index.html页面中jinja2渲染语法如下:

    <body>
        <table border="1"cellpadding="0"cellspacing="0">
            <tr>
                <td>{{ stu.id }}</td>
                <td>{{ stu.name }}</td>
                <td>{{ stu.get('age') }}</td>
                <td>{{ stu['gender'] }}</td>
            </tr>
        </table>
        <br>
     
        <table border="1"cellpadding="0"cellspacing="0">
            {% for item in stu_list %}
            <tr>
                <td>{{ item.name }}</td>
                <td>{{ item.get('age') }}</td>
                <td>
                    {% if item['gender']=='male' or item['gender']=='female' %}
                    {{ item['gender'] }}
                    {% else %}
                    male
                    {% endif %}
                </td>
            </tr>
            {% endfor %}
        </table>
        <br>
    
        <table border="1"cellpadding="0"cellspacing="0">
            {% for key,value in stu_dict.items() %}
            <tr>
                <td>{{ key }}</td>
                <td>{{ value.name }}</td>
                <td>{{ value.get('age') }}</td>
                <td>{{ value['gender'] }}</td>
            </tr>
            {% endfor %}
        </table>
    </body>
    

    总结: 对比django可以发现几点不同:

    • 第一, jinja2语法也可以调用方法, 但调用方法要加括号;
    • 第二, jinja2中字典取值除了可以使用点(.)语法, 还有字典的get方法和[key]取值.

    (2)引用变量和执行函数都使用{{}}

    {{}}除了可以传递变量, 还可以传递函数, 如下所示:

    def add(a,b):
        return a+b
    
    @app.route('/index')
    def index():
        return render_template('index.html', func=add)
    

    在模板文件index.html中直接使用{{ func(1,2) }}便可以渲染出函数执行的结果.

    (3)写逻辑代码时使用{%%}

    (4)Markup安全标签字符串

    为了防止xss攻击, flask会把传递给模板文件的数据转换为文本格式, 例如:

    # 视图函数app.py
    
    @app.route("/markup")
    def markup():
        html = "<h1>markup_test</h1>"
        return render_template("markup.html", html=html)
    
    # 模板文件markup.html
    
    {{ html }}
    

    使用Markup可以解决这个问题, Markup 安全标签字符串, 相当于django中的过滤器safe, 使用方法如下:

    # 视图函数app.py
    
    @app.route("/new_markup")
    def new_markup():
        html = "<h1>markup_test</h1>"
        new_html = Markup(html)
        return render_template("markup.html", html=new_html)
    
    # markup.html
    
    {{ html }}
    

    (5)装饰器@app.template_global()

    我们虽然可以使用render_template()等方式向模板页面中传递函数, 但是如果有许多页面都需要执行同一个函数, 就不得不向每一个页面都传递一次. 使用装饰器template_global()则简便得多, 只需书写一次, 就可以在任何一个模板文件中都使用该函数了.

    @app.template_global()
    def add(a, b):
        return a + b
    

    在任何一个模板文件中都可以调用add函数: {{ add(1, 2) }}

    (6)装饰器@app.template_filter()

    @app.template_filter()
    def fil(a, b, c):
        return a + b + c
    

    在模板文件中使用方法是 {{ 2|fil(3, 4) }}, 与django中的过滤器用法相似: 管道符前面的数作为fil函数的第一个参数, 管道符后面的函数fil直接调用执行.

    (7)宏指令(使用较少)

    # 视图函数macro.py
    
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    
    @app.route("/macro")
    def macro():
        return render_template("macro.html")
    
    
    if __name__ == '__main__':
        app.run()
    
    # 模板文件macro.html
    
    <body>
    {% macro create_input(ty, na) %}
        {{ na }}: <input type="{{ ty }}" name="{{ na }}">
    {% endmacro %}
    {{ create_input("text", "username") }}
    {{ create_input("password", "password") }}
    </body>
    

    (8)继承和导入

    flask模板文件的继承和导入同django类似:

    • 一个页面中导入另一个页面: {% include "header.html" %}
    • 一个页面继承另一个页面: {% extends "base.html" %}
    • 定义block块: {% block 名字 %}

    7. Flask中的session(公共变量)

    from flask import Flask
    
    app = Flask(__name__)
    
    app.secret_key = "salt"  # salt是加密字符串,可随意设置,用于序列化和反序列化session信息
    

    我们知道cookie和session的区别是cookie存在客户端,session存在服务器端,但是flask中为了节省开销,Flask中默认Session 存放位置是客户端的Cookies中,因此在flask中用Session需要加密,也就是一定要加secret_key。

    • flask中添加一个session的语法: session["user"]="%^$&@!"
    • 工作机制: 由secret_key + session加密后存放在浏览器的cookie中
    • 验证session机制: 当请求进入视图函数, 带上cookie, 将session从cookie序列化出来, 通过secret_ley反序列化成字典
  • 相关阅读:
    在Chrome浏览器中保存的密码有多安全?
    进程上下文切换 – 残酷的性能杀手(上)
    进程上下文切换 – 残酷的性能杀手(下)
    javascript推荐书籍
    使用Visual Studio 利用WinGDB编译和远程调试嵌入式Linux的程序
    Source Insight 3.X 标签插件v1.0发布
    QQ空间自动发广告解决方法
    Java---实力弹弹球,弹弹弹
    HDOJ 2027 统计元音
    Java---计算机贷款支付额计算(用对话框实现)
  • 原文地址:https://www.cnblogs.com/haitaoli/p/10466567.html
Copyright © 2011-2022 走看看