Flask基础


Flask基础

Flask是一个Python编写的Web微框架,让我们可以使用Python语言快速实现一个网站或Web服务

# 安装flask
pip install flask

1.flask对象

创建flask_demo01_hello_world.py

# 1. 从 flask 模块导入 Flask 类
from flask import Flask

# 2.创建 flask 对象
# 参数1:__name__,如果从当前文件启动,那么值是__main__,如果是从其他模块调用运行的那么值是模块的名字
# 参数2:static_url_path,表示静态资源【CSS、Img……】的访问地址,/static
# 参数3:static_folder,用于存储静态资源的文件夹,默认文件名为:static
# 参数4:template_folder,模板文件夹,特指html文件,默认文件名为:templates
app = Flask(__name__)


# 使用app,通过路由绑定一个视图函数
# 注意:视图函数必须有返回值
@app.route("/")
def helloworld():
    return "hello world Flask"


# 判断是否直接使用当前模块运行程序
# 如果 __name__ == "__main__" 那么运行当前程序
if __name__ == "__main__":
    # 运行当前程序,http://127.0.0.1:5000
    app.run(debug=True)
    # app.run() 参数
    # 参数1:host,默认 127.0.0.1
    # 参数2:post,默认 5000
    # 参数3:debug,默认 False

2.URL路由选择器

创建flask_demo02_url_map.py

"""
查看哪些路由(地址)可以访问
- 格式:使用 app.url_map,返回的是 app 装饰的所有路由和路径之间的关系
- 注意点:只有被 app.url_map 包含进来的路由(地址)才能被访问
"""


from flask import Flask

app = Flask(__name__)


@app.route("/")
def index():
    return "this is index"


@app.route("/home")
def home():
    return "this is home"


if __name__ == "__main__":
    print(app.url_map)
    app.run(debug=True)

创建flask_demo03_dynamic_params.py

"""
在访问路由的时候指定参数【动态参数】

 - 格式:@app.route("/<类型:变量名>")
 - 常见参数类型(默认 path)
    - 整数:int
    - 小数:float
    - 字符串:path
"""


from flask import Flask

app = Flask(__name__)


# 接收一个整数
@app.route("/<int:number>")
def get_intNumber(number):
    return f"the int is {number}"


# 接收一个小数
@app.route("/<float:number>")
def get_floatNumber(number):
    return f"the float is {number}"


# 接收一个字符串
@app.route("/<path:number>")
def get_pathNumber(number):
    return f"the path is {number}"


if __name__ == "__main__":
    app.run(debug=True)

创建flask_demo04_custom_converter.py

"""
自定义参数类型(自定义转换器)

 - 背景:
   - 如果系统提供的 int,float 等参数类型满足不了需求的时候,我们需要自定义
   - 之所以 int,float,path 可以接收不同的数据类型,是因为,系统已经提供好对应的转换器了
 - 自定义转换器格式
   - 1. 定义类,继承自 BaseConverter
   - 2. 重写 init 方法
   - 3. 初始化父类成员变量,还有子类自己的规则
   - 4. 将转换器类添加到系统默认的转换器列表中

   需求:接收三位整数
"""


import typing as t
from flask import Flask
from werkzeug.routing import BaseConverter
from werkzeug.routing.map import Map

app = Flask(__name__)


# - 1. 定义类,继承自 BaseConverter
class MyRegexConverter(BaseConverter):
    # 接收三位整数
    # regex = "\d{3}"  # 直接指定规则不灵活,具体匹配什么规则应该交给路由

    #  - 2. 重写 init 方法
    # 接收两个参数:map 和 regex
    def __init__(self, map, regex) -> None:
        # - 3. 初始化父类成员变量,还有子类自己的规则
        super(MyRegexConverter, self).__init__(map)
        self.regex = regex


# - 4. 将转换器类添加到系统默认的转换器列表中
app.url_map.converters["threeDigit"] = MyRegexConverter


# 匹配三位整数
@app.route("/<threeDigit('\d{3}'):number>")
def get_threeNumber(number):
    return f"the threeNumber is {number}"


# 匹配四位整数
@app.route("/<threeDigit('\d{4}'):number>")
def get_fourNumber(number):
    return f"the fourNumber is {number}"


# 匹配一个手机号
@app.route("/<threeDigit('^1[3-9]\d{9}'):number>")
def get_phoneNumber(number):
    return f"the phoneNumber is {number}"


if __name__ == "__main__":
    app.run(debug=True)

创建flask_demo05_methods.py

"""
给路由增加其他的访问方式
- 格式:@app.route('路径', methods=['请求方式1', '请求方式2', ...])
- 常见的请求方式:
  - GET,POST,PUT,DELETE

- 注意:如果不指定请求方式,默认支持 GET 请求

- 发送 POST 请求:
  - 1. 写一个表单
  - 2. 发送一个 ajax 请求
  - 3. 使用 postman 发送 post 请求
"""


from flask import Flask

app = Flask(__name__)


@app.route("/", methods=["POST", "GET"])
def helloworld():
    return "hello world Flask"


if __name__ == "__main__":
    app.run(debug=True)

3.返回值

创建flask_demo06_return_response.py

"""
返回响应(字符串)

- 1. 直接返回响应体数据
    - return '字符串'
- 2. 直接返回响应体数据+状态码
    - return '字符串', 状态码
- 3. 直接返回响应体数据+状态码+响应头信息
    - return '字符串', 状态码, {'key', 'value'}
"""


from flask import Flask

app = Flask(__name__)


@app.route("/")
def helloworld():
    # - 1. 直接返回响应体数据
    # return "hello world Flask"

    # - 2. 直接返回响应体数据+状态码
    # return "hello world Flask", 666
    # return "hello world Flask", "666 BIGERROR"

    # - 3. 直接返回响应体数据+状态码+响应头信息
    return (
        "hello world Flask",
        200,
        {"Content-Type": "application/json", "name": "wang"},
    )


if __name__ == "__main__":
    app.run(debug=True)

创建flask_demo07_jsonify.py

"""
通过 jsonify 返回json数据
- 格式:jsonify(dict)
- 简化格式:jsonify(key1=value1, key2=value2)
"""
from flask import Flask, jsonify

app = Flask(__name__)


@app.route("/")
def helloworld():
    # 1. 定义字典
    dict = {"name": "wang", "age": 23}

    # 2. 返回json数据
    # return jsonify(dict)

    # 3. 返回json数据简化格式
    return jsonify(name="zhao", age=22)


if __name__ == "__main__":
    app.run(debug=True)

4.重定向

创建flask_demo08_redirect.py

"""
重定向
- 格式:redirect('地址'),地址既可以是本地服务器的地址,也可以是其他服务器地址
- 注意点:重定向的代号是302
- 特点:重定向是两次请求
"""


from flask import Flask, redirect

app = Flask(__name__)


@app.route("/")
def helloworld():
    return redirect("/index")


@app.route("/index")
def index():
    return "this is index"


if __name__ == "__main__":
    app.run(debug=True)

创建flask_demo09_redirect_practice.py

"""
重定向
- 格式:redirect('地址'),地址既可以是本地服务器的地址,也可以是其他服务器地址
- 注意点:重定向的代号是302
- 特点:重定向是两次请求
"""

from flask import Flask, redirect

app = Flask(__name__)


@app.route("/")
def helloworld():
    return redirect("/taobao")


@app.route("/taobao")
def taobao():
    # 重定向到淘宝网
    return redirect("https://www.taobao.com/")


@app.route("/index")
def index():
    return "this is index"


if __name__ == "__main__":
    app.run(debug=True)

5.反向解析

创建flask_demo10_url_for.py

"""
url_for

- 解释:称为反解析,返回的是视图函数对应的路由地址
- 格式:url_for('视图函数', key=value)
- 注意:url_for 经常和redirect配合使用,传递参数
    - 例如:response = redirect(url_for("taobao", token=123))
"""


from flask import Flask, redirect, url_for

app = Flask(__name__)


@app.route("/")
def helloworld():
    return "hello world Flask"


@app.route("/jingdong")
def jingdong():
    # 1. 通过 url_for 找到taobao的地址,然后通过redirect进行重定向
    response = redirect(url_for("taobao", token=123))
    # 2. 返回响应体对象
    return response


@app.route("/pinduoduo")
def pinduoduo():
    response = redirect(url_for("taobao", token=456))
    return response


@app.route("/taobao/<int:token>")
def taobao(token):
    if token == 123:
        return "欢迎京东用户!"
    elif token == 456:
        return "欢迎拼多多的用户!"
    else:
        return "欢迎其他用户!"


if __name__ == "__main__":
    app.run(debug=True)

创建flask_demo11_abort_errorhandler.py

"""
abort & errorhandler

- 使用场景:当访问服务器资源的时候,如果找不到该资源可以报出异常信息,使用errorhandler捕捉
- 格式:abort(代号)
- 格式:@app.errorhandler(代号)
"""


from flask import Flask, abort

app = Flask(__name__)


@app.route("/")
def helloworld():
    abort(403)

    return "hello world Flask"


@app.errorhandler(404)
def page_not_found(e):
    return "页面找不到"


@app.errorhandler(403)
def Forbidden(e):
    return "禁止访问"


if __name__ == "__main__":
    app.run(debug=True)

6.request

创建flask_demo12_request.py

"""
request 对象参数

- request.data: 获取非表单(ajax)以post提交的数据
- request.form: 获取表单以post提交的数据
- request.args: 获取问号后面的查询参数
- request.method: 获取的请求方式
- request.url: 获取请求的地址
- request.files: 获取input标签中type类型为file的文件
"""
from flask import Flask, request

app = Flask(__name__)


@app.route("/")
def helloworld():
    print(request.method)
    print(request.url)
    print(request.args)
    # print(request.args['name'])  # 字典不建议使用 [] 的方式进行取值,极易报错
    print(request.args.get("name"))  # 字典推荐使用 .get() 的方式取值
    print(request.args.get("age", 23))

    return "hello world Flask"


if __name__ == "__main__":
    app.run(debug=True)

7.加载参数

创建flask_demo13_load_appParams.py

"""
加载 app 程序运行参数

- 1. 从配置类(对象)中加载
    - app.config.from_object(obj)
- 2. 从配置文件中加载
    - app.config.from_pyfile(file)
- 3. 从环境变量中加载【了解即可】
    - app.config.from_envvar(环境变量)

- app.config: 表示 app 程序,运行所有的参数信息
"""

from flask import Flask

app = Flask(__name__)


# # 1. 从配置类(对象)中加载
# class MyConfig(object):
#     # 调试模式
#     DEBUG = True

# app.config.from_object(MyConfig)


# 2. 从配置文件中加载
app.config.from_pyfile("Config.ini")


@app.route("/")
def helloworld():
    return "hello world Flask"


if __name__ == "__main__":
    app.run()

创建Config.ini

DEBUG = True

8.请求钩子

创建flask_demo14_request_hook.py

"""
请求钩子

- 解释:当访问正常视图函数的时候,顺带执行的方法
- 常见的请求钩子有四种:

- 1. before_first_request:在处理第一个请求前执行【已不使用】
- 2. before_request:在每次请求前执行,在该装饰函数中,一旦return,视图函数不再执行
- 3. after_request:如果没有抛出错误,在每次请求后执行
    接收一个参数:视图函数作出的响应
    在此函数中可以对响应值,在返回之前做最后一步处理,再返回
- 4. teardown_request:再每次请求后执行
    接收一个参数:用来接收错误信息


- 顺序:
1. before_request
2. after_request
3. teardown_request
"""

from flask import Flask

app = Flask(__name__)


# 在flask2.3版本之后,该装饰器的功能在创建应用时运行,无需手动添加该装饰器
# @app.before_first_request
# def before_first_request():
#     print("before_first_request")


# 每次请求前都执行,适合对请求参数做校验,访问统计
@app.before_request
def before_request():
    print("before_request")


# 视图函数执行之后,返回该方法,适合对返回值做统一处理
@app.after_request
def after_request(resp):
    print("after_request")
    resp.headers["Content-Type"] = "application/json"
    return resp


# 请求销毁之后执行
@app.teardown_request
def teardown_request(e):
    print("teardown_request")


@app.route("/")
def helloworld():
    return "hello world Flask"


if __name__ == "__main__":
    app.run(debug=True)