zoukankan      html  css  js  c++  java
  • flask内容

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

    “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

    默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

    flask中虚拟环境的搭建(参考博客)

     1 sudo pip install virtualenv
     2 sudo pip install virtualenvwrapper
     3 
     4 # 1、创建目录用来存放虚拟环境
     5 mkdir
     6 $HOME/.virtualenvs
     7 
     8 # 2、打开~/.bashrc文件,并添加如下:
     9 export WORKON_HOME=$HOME/.virtualenvs
    10 source /usr/local/bin/virtualenvwrapper.sh
    11 
    12 # 3、运行
    13 source ~/.bashrc
    14 
    15 创建虚拟环境
    16 mkvirtualenv 虚拟环境名称
    17 例 :
    18 mkvirtualenv py_flask
    19 
    20 mkvirtualenv -p python3 虚拟环境名称
    21 例 :
    22 mkvirtualenv -p python3 py3_flask
    23 
    24 进入虚拟环境
    25 workon 虚拟环境名称
    26 
    27 例 :使用python2的虚拟环境
    28 workon py_flask
    29 
    30 例 :使用python3的虚拟环境
    31 workon py3_flask
    32 
    33 退出虚拟环境
    34 deactivate
    35 
    36 rmvirtualenv 虚拟环境名称
    37 
    38 例 :删除虚拟环境py3_flask
    39 
    40 先退出:deactivate
    41 再删除:rmvirtualenv py3_flask
    42 
    43 在虚拟环境中安装包
    44 pip install 包名称
    flask虚拟环境的搭建

     一,flask的基本使用:

     1 from flask import Flask
     2 
     3 app = Flask(__name__)
     4 
     5 
     6 @app.route('/')
     7 def hello_world():
     8     return 'Hello World!'
     9 
    10 
    11 if __name__ == '__main__':
    12     app.run(debug=True)
    flask的基本使用

     

    二,基本的配置

     1 # default_config = ImmutableDict({
     2 #     'DEBUG': False,
     3 #     'TESTING': False,
     4 #     'PROPAGATE_EXCEPTIONS': None,
     5 #     'PRESERVE_CONTEXT_ON_EXCEPTION': None,
     6 #     'SECRET_KEY': None,
     7 #     'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
     8 #     'USE_X_SENDFILE': False,
     9 #     'LOGGER_NAME': None,
    10 #     'SERVER_NAME': None,
    11 #     'APPLICATION_ROOT': None,
    12 #     'SESSION_COOKIE_NAME': 'session',
    13 #     'SESSION_COOKIE_DOMAIN': None,
    14 #     'SESSION_COOKIE_PATH': None,
    15 #     'SESSION_COOKIE_HTTPONLY': True,
    16 #     'SESSION_COOKIE_SECURE': False,
    17 #     'MAX_CONTENT_LENGTH': None,
    18 #     'SEND_FILE_MAX_AGE_DEFAULT': 12 * 60 * 60,  # 12 hours
    19 #     'TRAP_BAD_REQUEST_ERRORS': False,
    20 #     'TRAP_HTTP_EXCEPTIONS': False,
    21 #     'PREFERRED_URL_SCHEME': 'http',
    22 #     'JSON_AS_ASCII': True,
    23 #     'JSON_SORT_KEYS': True,
    24 #     'JSONIFY_PRETTYPRINT_REGULAR': True,
    25 # })
    26 
    27 
    28 
    29 方式一
    30  创建 Flask 类的对象,指向程序所在的包的名称
    31 app = Flask(__name__)
    32 
    33 # 从配置文件中加载配置
    34 app.config.from_pyfile('config.ini')
    35 
    36 方式二:
    37 # 配置对象,里面定义需要给 APP 添加的一系列配置
    38 class Config(object):
    39     # DEBUG = True
    40 
    41 
    42 # 创建 Flask 类的对象,指向程序所在的包的名称
    43 app = Flask(__name__)
    44 
    45 # 从配置对象中加载配置
    46 app.config.from_object(Config)
    配置文件的方式

    三,路由系统

    1 DEFAULT_CONVERTERS = {
    2     'default':          UnicodeConverter,
    3     'string':           UnicodeConverter,
    4     'any':              AnyConverter,
    5     'path':             PathConverter,
    6     'int':              IntegerConverter,
    7     'float':            FloatConverter,
    8     'uuid':             UUIDConverter,
    9 }

    路由关系的创建

     1 from flask import Flask
     2 from flask import request
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 # 指定访问路径为 demo1
     8 @app.route('/demo1')
     9 def demo1():
    10     return 'demo1'
    11 
    12 
    13 # 路由传递的参数默认当做 string 处理,也可以指定参数的类型
    14 @app.route('/user/<int:user_id>')
    15 def user_info(user_id):
    16     return 'hello %d' % user_id
    17 
    18 
    19 @app.route('/demo2', methods=['GET', 'POST'])
    20 def demo2():
    21     # 直接从请求中取到请求方式并返回
    22     return request.method
    23 
    24 
    25 if __name__ == '__main__':
    26     app.run(debug=True)
     1 from werkzeug.routing import BaseConverter
     2 from flask import Flask
     3 
     4 
     5 # 自定义正则转换器
     6 class RegexConverter(BaseConverter):
     7     def __init__(self, url_map, *args):
     8         super(RegexConverter, self).__init__(url_map)
     9         # 将接受的第1个参数当作匹配规则进行保存
    10         self.regex = args[0]
    11 
    12 
    13 app = Flask(__name__)
    14 
    15 # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
    16 app.url_map.converters['re'] = RegexConverter
    17 
    18 
    19 @app.route('/user/<re("[0-9]{3}"):user_id>')
    20 def user_info(user_id):
    21     return "user_id 为 %s" % user_id
    22 
    23 
    24 if __name__ == '__main__':
    25     app.run(debug=True)
    自定义路由正则
     1 from werkzeug.routing import BaseConverter
     2 from flask import Flask
     3 
     4 
     5 # 自定义正则转换器
     6 class RegexConverter(BaseConverter):
     7     def __init__(self, url_map, *args):
     8         super(RegexConverter, self).__init__(url_map)
     9         # 将接受的第1个参数当作匹配规则进行保存
    10         self.regex = args[0]
    11 
    12     def to_python(self, value):
    13         return int(value)
    14 
    15 
    16 app = Flask(__name__)
    17 
    18 # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
    19 app.url_map.converters['re'] = RegexConverter
    20 
    21 
    22 @app.route('/user/<re("[0-9]{3}"):user_id>')
    23 def user_info(user_id):
    24     print("user_id的类型为", type(user_id))
    25     return "user_id 为 %s" % user_id
    26 
    27 
    28 if __name__ == '__main__':
    29     app.run(debug=True)
    to_python方法
    1 to_url:
    2 在使用 url_for 去获取视图函数所对应的 url 的时候,会调用此方法对 url_for 后面传入的视图函数参数做进一步处理
    3 具体可参见 Flask 的 app.py 中写的示例代码:ListConverter
    to_url方法

    视图的常用逻辑

    不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,
    如果是 JSON 需要指定 content-type:application/json
     1 from flask import Flask
     2 from flask import jsonify
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 # 返回JSON
     8 @app.route('/demo4')
     9 def demo4():
    10     json_dict = {
    11         "user_id": 10,
    12         "user_name": "laowang"
    13     }
    14     return jsonify(json_dict)
    15 
    16 
    17 if __name__ == '__main__':
    18     app.run(debug=True)
    19 
    20 
    21 # 不推荐使用 json.dumps 转成 JSON 字符串直接返回,因为返回的数据要符合 HTTP 协议规范,
    22 # 如果是 JSON 需要指定 content-type:application/json
    数据的返回

    重定向

    重定向到指定的网址

     1 from flask import Flask
     2 from flask import redirect
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 @app.route('/demo5')
     8 def demo5():
     9     return redirect('http://www.itheima.com')
    10 
    11 
    12 if __name__ == '__main__':
    13     app.run(debug=True)

    重定向到自己写的函数中

    1 @app.route('/demo1')
    2 def demo1():
    3     return 'demo1'
    4 
    5 @app.route('/demo5')
    6 def demo5():
    7     return redirect(url_for('demo1'))

    重定向到带有参数的路由函数中

     1 # 路由传递参数
     2 @app.route('/user/<int:user_id>')
     3 def user_info(user_id):
     4     return 'hello %d' % user_id
     5 
     6 
     7 # 重定向
     8 @app.route('/demo5')
     9 def demo5():
    10     # 使用 url_for 生成指定视图函数所对应的 url
    11     return redirect(url_for('user_info', user_id=100))

      自定义状态码

    1 @app.route('/demo6')
    2 def demo6():
    3     return '状态码为 666', 666

    异常的捕获

     1 from flask import Flask
     2 from flask import abort
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 @app.route('/')
     8 def hello_world():
     9     return 'Hello World!'
    10 
    11 
    12 @app.route("/demo1")
    13 def demo1():
    14     # 主动http状态码
    15     abort(404)
    16     return "demo1"
    17 
    18 
    19 # 使用装饰器来捕获异常指定的状态码和异常
    20 @app.errorhandler(404)
    21 def page_not_fund(error):
    22     print(error)
    23     return "页面不存在"
    24 
    25 
    26 @app.route("/demo2")
    27 def div_demo2():
    28     a = 5
    29     b = 0
    30     return a / b
    31 
    32 
    33 # 使用错误捕获来捕获除数不能为0的的错误
    34 @app.errorhandler(ZeroDivisionError)
    35 def Zero_Division_Error(error):
    36     print(error)
    37     return "除数不能为0"
    38 
    39 
    40 # 第二种捕获异常的方式
    41 # def page_not_found(error):
    42 #     return '你访问的页面不存在', 404
    43 # app.error_handler_spec[None][404] = page_not_found
    44 
    45 
    46 
    47 if __name__ == '__main__':
    48     app.run(debug=True)
    View Code

      注册一个处理程序错误的装饰器,当程序抛出指定错误状态码的时候会调用装饰器所装饰的方法(除了捕获异常的状态码之外还可以捕获指定的异常)

    flask中的请求钩子

     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 
     4 from flask import Flask
     5 
     6 app = Flask(__name__)
     7 
     8 
     9 @app.before_first_request
    10 def before_first_request():
    11     print("before_first_request")
    12 
    13 
    14 @app.before_request
    15 def before_request():
    16     print("before_request")
    17 
    18 
    19 @app.after_request
    20 def after_request(response):
    21     print("response", response)
    22     print("after_request")
    23     return response
    24 
    25 
    26 # 在请求之后可以被执行,如果有异常会将此异常传入到这个函数来做处理
    27 @app.teardown_request
    28 def teardown_request(error):
    29     print(error)
    30     print("teardown_request")
    31 
    32 
    33 @app.route('/')
    34 def index():
    35     print("index", index)
    36     return 'index'
    37 
    38 
    39 if __name__ == '__main__':
    40     app.run(debug=True)
    View Code
    before_first_request(在处理第一个请求前执行,后续的执行过程就不会再执行了)
    before_request(每次发起请求前都会执行,如果在某个修饰函数中返回一个响应,视图函数将不再被调用)
    after_request

    没有抛出异常,则在每次请求后会执行
    接收一个参数:视图函数做出的响应;
    在此函数中可以对视图函数做出的响应做最后一步的处理;
    需要将参数中的响应在此函数中返回

    teardown_request

    每次请求之后都会执行;
    接收一个参数:如果抛出异常,则参数会捕捉到这个异常;


     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 
     4 from flask import Flask,request
     5 from werkzeug.serving import run_simple
     6 
     7 app = Flask(__name__)
     8 
     9 
    10 @app.route('/')
    11 def hello_world():
    12     return 'Hello World!'
    13 
    14 @app.route('/index', methods=["POST",])
    15 def index():
    16     print(request.method)
    17     return 'index index!'
    18 
    19 # rule 视图函数和酷游关系的映射关系
    20 # map rule的集合
    21 # BaseConverter匹配路由匹配的规则
    22 # MapAdapter协调以上的路由匹配的工作
    23 
    24 
    25 if __name__ == '__main__':
    26     print(app.url_map)
    27     app.run(debug=True)
    装饰器路由功能的实现

    Werkzeug库的 routing 模块负责实现 URL 解析。不同的 URL 对应不同的视图函数,routing模块会对请求信息的URL进行解析,匹配到URL对应的视图函数,执行该函数以此生成一个响应信息。

    routing模块内部有:

      • Rule类
        • 用来构造不同的URL模式的对象,路由URL规则
      • Map类
        • 存储所有的URL规则和一些配置参数
      • BaseConverter的子类
        • 负责定义匹配规则
      • MapAdapter类
        • 负责协调Rule做具体的匹配的工作

    请求上下文(request context)

     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 
     4 
     5 from flask import Flask
     6 from flask import request
     7 
     8 app = Flask(__name__)
     9 
    10 
    11 @app.route('/index', methods=["GET", "POST"])
    12 def index():
    13     return 'Hello World!'
    14 
    15 
    16 @app.route("/args", methods=["GET", "POST"])
    17 def args():
    18     # get方式地址栏传递参数
    19     print(request.form.get("name"))
    20     print(request.form.get("age"))
    21     # post方式请求体中传递参数
    22     print(request.args.get("name"))
    23     print(request.args.get("age"))
    24     return "success"
    25 
    26 
    27 @app.route("/file", methods=["POST"])
    28 def up_load_file():
    29     print(request.method)
    30     pic = request.files.get("pic")
    31     pic.save("./static/aaaa.png")
    32     return "success"
    33 
    34 
    35 if __name__ == '__main__':
    36     app.run(debug=True)
    request的使用

    request是flask中代表当前请求的request对象,是一个全局的请求上下文的一个变量(可以理解成为一个全局变量,在视图函数中可以直接使用,可以取到当前请求)。

     备注:在地址栏中请求数据的方式可以用args的方式去在request中取值,如果在form表单中的数据需要在form中取值。

    cookie的设置

     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 
     4 from flask import Flask
     5 from flask import request
     6 from flask import make_response
     7 
     8 app = Flask(__name__)
     9 
    10 
    11 # 获取cookies
    12 @app.route('/index')
    13 def index():
    14     username = request.cookies.get("username")
    15     user_id = request.cookies.get("user_id")
    16     return '%s---%s' % (username, user_id)
    17 
    18 
    19 # 设置cookies
    20 @app.route("/login")
    21 def login():
    22     response = make_response("success")
    23     response.set_cookie("username", "xiaoimng", max_age=3600)
    24     response.set_cookie("user_id", "1", max_age=3600)
    25     return response
    26 
    27 
    28 # 删除cookies
    29 @app.route("/logout")
    30 def logout():
    31 
    32     response = make_response("删除cookies成功")
    33     response.delete_cookie("user_id")
    34     response.delete_cookie("username")
    35     return response
    36 
    37 
    38 if __name__ == '__main__':
    39     app.run(debug=True)
    cookie的设置

    备注:

    1,cookie的设置是在response中进行设置,在request中取值;

    2,http是一种无状态的协议,浏览器在请求服务器的时候是无状态的,

    无状态的原因是:

    浏览器与服务器通过socket进行通信,服务器会将请求结果返回给浏览器,请求完毕后服务器都会将通信套接字关闭,并且服务器在关闭套接字之后就会销毁请求的页面的对象;

    有时需要保持浏览器的状态,比如用户的登录状态,和浏览过的信息等;

    无状态协议

    1,协议对事物的处理没有记忆的功能;

    2,对于同一个url请求没有上下文的关系;

    3,每次执行的结果都是独立的,它执行的结果和情况与上前面的请求和之后的请求没有直接的关系,它不会受前面的请求应答的影响,也不会对后面的请求应答产生影响;

    4,服务器没有保持客户端的状态,客户端每次需要自己将状态带到服务区端;

    实现状态保持有两种方式;

    1,在客户端设置cookie,在每次发送请求的时候将cookie带给服务器端;

    2,在服务器端设置session,每次客户福安发送来请求之后,将客户端的cookie与session做做对比;(所有说session是依赖于cookie的,cookie可以单独存在session不可以独立存在);

     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 from datetime import timedelta
     4 from flask import Flask
     5 from flask import session
     6 
     7 app = Flask(__name__)
     8 app.config["SECRET_KEY"] = "abcdefg"
     9 
    10 
    11 # app.secret_key["SECRET_KEY"] = "abcsefght"
    12 
    13 @app.route('/index')
    14 def index():
    15     user_name = session.get("user_name")
    16     user_id = session.get("user_id")
    17     return "%s---%s" % (user_name, user_id)
    18 
    19 
    20 @app.route("/login")
    21 def login():
    22     session.permanent = True
    23     app.permanent_session_lifetime = timedelta(second=10)
    24     session["user_name"] = "xiaomingh"
    25     session["user_id"] = "1"
    26     return "session设置成功"
    27 
    28 
    29 @app.route("/logout")
    30 def logout():
    31     session.pop("user_name", None)
    32     session.pop("user_id", None)
    33     return "session删除删除成功"
    34 
    35 
    36 if __name__ == '__main__':
    37     app.run(debug=True)
    session的设置

     

    思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等

    在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session

      • request
        • 封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。
      • session
        • 用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。

    应用上下文(application context)

    它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。

    应用上下文对象有:current_app,g

    current_app

    应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:

      • 应用的启动脚本是哪个文件,启动时指定了哪些参数
      • 加载了哪些配置文件,导入了哪些配置
      • 连了哪个数据库
      • 有哪些public的工具类、常量
      • 应用跑再哪个机器上,IP多少,内存多大
    current_app.name
    current_app.test_value='value'
    

    g变量

    g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别

     





    flask_script
     1 #! /usr/bin/env python
     2 # *-* coding: utf-8 *-*
     3 
     4 
     5 from flask import Flask
     6 # 请求上下文的变量
     7 from flask import request, make_response
     8 # 运用上下文的变量
     9 from flask_script import Manager
    10 from flask import current_app
    11 from flask import g
    12 
    13 app = Flask(__name__)
    14 app.debug = True
    15 manager = Manager(app)
    16 
    17 
    18 @app.route('/')
    19 def hello_world():
    20     # 类似于一个全局变量的东西
    21     print(current_app.config.get("DEBUG"))
    22     return 'Hello World!'
    23 
    24 
    25 if __name__ == '__main__':
    26     manager.run()
    27     # app.run(debug=True)
    View Code

    通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过:

    python hello.py runserver -host ip地址


  • 相关阅读:
    JQuery的Dom操作
    JQuer的简单应用
    JSBom联合Dom的应用
    Bom—浏览器对象模型
    正则表达式(其实就是预习)
    Js关于表单的事件应用
    JavaScript事件练习
    微信小程序实现微信登录
    Azure 数据资源管理器 -- 当 ADX 遇上 ML
    多快好省 -- Azure VMSS AI 推理篇
  • 原文地址:https://www.cnblogs.com/cerofang/p/9200949.html
Copyright © 2011-2022 走看看