zoukankan      html  css  js  c++  java
  • 初识 Flask

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比

    1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不管你用得到用不到,反正它全都有,属于全能型框架

    2.Tornado 主要特点是原生异步非阻塞,在IO密集型应用和多任务处理上占据绝对性的优势,属于专注型框架

    3.Flask 主要特点小而轻,原生组件几乎为0, 三方提供的组件请参考Django 非常全面,属于短小精悍型框架

    Django 通常用于大型Web应用由于内置组件足够强大所以使用Django开发可以一气呵成

    Tornado 通常用于API后端应用,游戏服务后台,其内部实现的异步非阻塞真是稳得一批

    Flask 通常应用于小型应用和快速构建应用,其强大的三方库,足以支撑一个大型的Web应用

    Django 优点是大而全,缺点也就暴露出来了,这么多的资源一次性全部加载,肯定会造成一部分的资源浪费

    Tornado 优点是异步,缺点是干净,连个Session都不支持

    Flask 优点是精悍简单

    总结:

    Flask:
        优点:小而精,短小精悍,第三方组件特别多
        缺点:组件更新速度取决于开源者,你不会
        
    Tornado:
        优点:原生的WebSocket,异步任务,IO非阻塞
        缺点:组件没有,Session都没有
        
    Django:
        优点:大而全,组件非常全面
        缺点:太大,加载太大,浪费资源

     二、Flask 的安装与简单使用

    pip install Flask

    最简单的Flask项目,Flask三行:

    from flask import Flask
        apl = Flask(__name__)
        apl.run()

    三、三种返回页面的方式

    from flask import Flask, render_template, redirect
    
    # 一个flask对象
    app = Flask(__name__)
    
    STUDENT_LIST = [ {'name': 'Old', 'age': 38, 'gender': '中'},
               {'name': 'Boy', 'age': 73, 'gender': '男'},
               {'name': 'EDU', 'age': 84, 'gender': '女'} ]
    # render 注意, templates文件要和当前py文件同级,不然会找不到,报一个Jinja2的异常哦 @app.route('/index') def index(): html_msg = '<h1>my html</h1>' markup_tag = Markup(html_msg) # 相当于在html页面加上 safe ,这里写了,前端页面就不用写了 return render_template('index.html', stu=STUDENT_LIST, markup_tag=markup_tag, tag="") # HTTPResponse @app.route('/') def one_test(): return 'hello girl' # redirect @app.route('/hello') def hello(): return redirect('/index')


    if __name__ == '__main__':
        # debug模式运行
        app.run(debug=True)

    四、模版语言

    1.模版函数

    2、数据安全

    3、 for if 等的用法和django里的一样

    4、模版继承的用法也和django一样,就不写了

    举个栗子:

    在 app.py 中

    #########  在Jinja2中执行Python函数(模板中执行函数) ############
    @app.template_global()  # 定义全局模板函数
    def a_b_sum(a, b):
        return a + b
    
    
    @app.template_filter()  # 定义全局模板函数
    def a_b_c_sum(a, b, c):
        return a + b + c
    
    
    def index():
        html_msg = '<h1>my html</h1>'
        markup_tag = Markup(html_msg)  # 相当于在html页面加上 safe ,这里写了,前端页面就不用写了
        return render_template('index.html', stu=STUDENT_LIST, markup_tag=markup_tag, tag="")

    在index.html页面里

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <!-- 在Jinja2中执行Python函数(模板中执行函数) -->
         {{ a_b_sum(99,1) }}
        <br>
        {{ 1 | a_b_c_sum(197,2) }}
    
        <!-- 插入 markup 处理后的html标签 -->
        {{ markup_tag }}     
    
      <table>
          <thead>
          <tr>
              {% for foo in stu[0] %}
                <td>{{ foo }}</td>
              {% endfor %}
          </tr>
          </thead>
          <tbody>
            {% for st in stu %}
                <tr>
                    {% for t in st %}
                        <td>{{ st[t] }}</td>
                    {% endfor %}
    
                </tr>
            {% endfor %}
          </tbody>
      </table>
    
    </body>
    </html>

    五、一个简单的登录认证

    1、request 的使用

    2、session的应用

    • Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪
    • secret_key 实际上是用来加密字符串的,如果在实例化的app中没有 secret_key 那么开启session一定会抛异常的
    • cookies 中 session 存储的是通过 secret_key 加密后的 key , 通过这个 key 从flask程序的内存中找到用户对应的session信息

    3、装饰器的使用及遇到的问题

    4、类似Django中间件,.@app.before_request 和 @app.after_request    errorheadler

    先看代码吧~

    在app.py中:

    from flask import Markup  # 导入 flask 中的 Markup 模块 
    from flask import Flask, render_template, redirect 
    from flask import request 
    from flask import session
    
    # 一个flask对象 
    app = Flask(__name__) 
    # cookies 中 session 存储的是通过 secret_key 加密后的 key , 通过这个 key 从flask程序的内存中找到用户对应的session信息 
    app.secret_key = "LYJ" 
    
    import functools
    
    # 一个认证装饰器
    def my_auth(func):
        @functools.wraps(func)
        def war(*args, **kwargs):
            if session.get('user'):
                return func()
            else:
                return redirect('/login')
    
        return war
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            print(request.form)  # ImmutableMultiDict([('username', 'qwe'), ('pwd', '123')])
            username = request.form['username']  # 以字典方式取值
            pwd = request.form.get('pwd')
            print(username, pwd)
    
            # session的应用
            session['user'] = username
            return redirect('/index')
        if request.method == 'GET':
            return render_template('login.html')
    
    
    # 认证,自定义装饰器的使用
    @app.route('/index2', endpoint='index2')
    @my_auth
    def index2():
        return redirect('/index')  #用的是示例模版的那个index
    
    
    @app.route('/index3', endpoint='index3')
    @my_auth
    def index3():
        return redirect('/index')
    
    
    #  AssertionError: View function mapping is overwriting an existing endpoint function: war
    # 因为在经过装饰器后 func 的 __name__都变成了装饰器的名字,所以 route 在处理时,会取到多个一样的方法名
    # 有两种解决办法 1、 在装饰器中加上 装饰器修复  @functools.wraps(func)  2、 用endpoint给传入route的函数命名: @app.route('/index3',endpoint='index3')
    
    
    if __name__ == '__main__':
        # debug模式运行
        app.run(debug=True)

    如果直接加装饰器的话,会报错

    AssertionError: View function mapping is overwriting an existing endpoint function: war

     原因:在经过装饰器后 func 的 __name__都变成了装饰器的名字,所以 route 在处理时,会取到多个一样的方法名
    有两种解决办法 

    1、 在装饰器中加上 装饰器修复  @functools.wraps(func) 

    2、 用endpoint给传入route的函数命名: @app.route('/index3',endpoint='index3')

    注意:

      装饰器应该放在最靠近函数的地方,因为装饰器的执行顺序是从最靠近的那个开始的,不这样写的话会不行该函数,详见:多个装饰器的执行顺序

     另一种处理登录认证的方式,类似于Django的中间件 

    1.@app.before_request 在请求(request)之前做出响应

    from flask import Flask
    from flask import request
    from flask import redirect
    from flask import session
    
    app = Flask(__name__)  # type:Flask
    app.secret_key = "DragonFire"
    
    
    @app.before_request
    def is_login():
        if request.path == "/login":
            return None
    
        if not session.get("user"):
            return redirect("/login")
    
    
    @app.route("/login")
    def login():
        return "Login"
    
    
    @app.route("/index")
    def index():
        return "Index"
    
    
    @app.route("/home")
    def home():
        return "Login"
    
    
    app.run("0.0.0.0", 5000)

    @app.before_request 也是一个装饰器,他所装饰的函数,都会在请求进入视图函数之前执行

    request.path 是来读取当前的url地址如果是 /login 就允许直接通过 return None 你可以理解成通过放行

    校验session中是否有user 如果没有的话,证明没有登录,所以毫不留情的 redirect("/login") 跳转登录页面

    还有一个要提的 @app.before_first_request 它与 @app.before_request 极为相似或者说是一模一样,只不过它只会被执行一次

    2. @app.after_request 在响应(response)之前做出响应

    @app.after_request
    def foot_log(environ):
        if request.path != "/login":
            print("有客人访问了",request.path)
        return environ

    3. errorheadler(404) 定义错误信息

    def error_page(arg)
          错误信息头

    4、flash 导入  

      flash("message")
      get_flashed_messages() 导入

    一存放,一提取,消失 

    很少应用,但是要了解有这么个东西

  • 相关阅读:
    C#异步调用的好处和方法
    asp.net运行原理
    基于jQuery的AJAX和JSON的实例
    Slq Server创建索引
    SQL查询一个表中类别字段中Max()最大值对应的记录
    优化SQL Server的内存占用之执行缓存
    ASP.NET缓存
    .NET Framework 4.5新特性
    ADO.NET 连接数据库字符串(Oracle、SqlServer、Access、ODBC)
    sql server基础
  • 原文地址:https://www.cnblogs.com/95lyj/p/9508443.html
Copyright © 2011-2022 走看看