Flask 快速入门

153 阅读5分钟

概述:Django与Flask的区别

Django是一个大而全的框架,Flask是一个轻量级的框架;

Django内部为我们提供了非常多的组件:orm/session/cookie/admin/form/modelform/视图/路由/模板/中间件/分页/auth(认证)/contenttype/缓存/信号/多数据库连接 等。

Flask框架本身没有太多功能:路由/视图/模板(jinja2)/session,第三方组件非常齐全。

注意:Django的请求处理是逐一封装并传递,Flask的请求是利用上下文管理来实现的。(请求会被放在特殊的地方,需要请求时去特定的地方取)

Flask快速使用

安装

pip3 install flask

依赖wsgi(web服务网关接口) Werkzeug

from werkzeug.serving import sun_simple

def func(environ, start_response):
    pass
    
host = '127.0.0.1'
port = 5000

if __name__=='__main__':
    run_simple(host, port, func, **option)  #host: 主机名,port: 端口

Hello, World

from flask import Flask

# app是实例化的Flask对象
app = Flask(__name__)  # name是模块名


# url /index 会对应上函数index()
@app.route('/index')
def index()
    return "Hello, world"
    
if __name__=='__main__':
    app.run()  # 执行了Flask类的run()方法
class Flask(App):
    ...
    def run(
        self,
        host: str | None = None,
        port: int | None = None,
        debug: bool | None = None,
        load_dotenv: bool = True,
        **options: t.Any,
    ) -> None:
        ...
        try:
            # self即app对象
            # 请求进来,会执行__call__()方法
            run_simple(t.cast(str, host), port, self, **options)
        # 这段代码是Flask框架中的一部分,它位于`app/run.py`文件中。
        # 这段代码定义了一个名为`run_simple`的函数,它接受以下参数:

        # - `host`: 主机名或IP地址,用于指定要运行Flask应用程序的服务器。
        # - `port`: 端口号,用于指定要运行Flask应用程序的服务器上的端口。
        # - `self`: Flask应用程序实例。
        # - `**options`: 其他选项,如`use_reloader`、`use_debugger`、`use_evalex`等。

        # `run_simple`函数的目的是在指定的服务器上运行Flask应用程序。
        # 它首先使用`cast`函数将`host`参数转换为字符串类型,
        # 然后使用`run_simple`函数在指定的服务器上运行Flask应用程序。

        # `run_simple`函数的实现依赖于`werkzeug.serving.run_simple`函数。
        # 它使用`werkzeug.serving.run_simple`函数在指定的服务器上运行Flask应用程序,
        # 并处理各种选项,如自动重新加载、调试等。
        ...
        
    def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:

        return self.wsgi_app(environ, start_response)
        
        # 这段代码是Flask框架中`Flask`类的一个方法`__call__`的实现。
        # 它是Flask应用程序的核心方法,当Flask应用程序被作为WSGI应用程序调用时,它会执行这个方法。

        # `__call__`方法接收两个参数:`environ`和`start_response`。
        # `environ`是一个字典,包含当前请求的所有环境变量,例如请求方法(GET、POST等)、请求路径、请求头等信息。
        # `start_response`是一个可调用对象,它用于设置响应的状态码、响应头和响应缓冲区。

        # `__call__`方法的主要目的是处理请求,并将处理结果返回给WSGI服务器。
        # 它首先调用`self.wsgi_app`方法,该方法是Flask应用程序的WSGI应用程序,它将处理请求并返回响应。
        # 然后,它将响应结果和`start_response`参数传递给`start_response`方法,
        # 以便WSGI服务器可以将响应发送给客户端。

        # 总之,`__call__`方法是Flask应用程序的核心功能,它处理请求、调用WSGI应用程序并返回响应,
        # 从而使Flask应用程序成为了一个完整的WSGI应用程序。

本质是由werkzeug来实现的。 image.png

总结

  • Flask框架是基于werkzeug的wsgi实现的,Flask自己没有wsgi。
  • 用户请求一旦到来,就会执行app.__call__()方法。
  • 写Flask的标准流程:创建Flask对象,匹配路由和视图函数,app.run

实现一个XX管理系统

用户登录&用户管理

from flask import Flask, render_template, \
    jsonify, redirect, url_for, request  # 导入的request就是请求

app = Flask(__name__)

DATA_DICT = {
    1: {'name': '张三', 'age': 18},
    2: {'name': '李四', 'age': 20},
}


@app.route('/login', methods=['GET', 'POST'])  # 支持GET和POST请求
def login():

    if request.method == 'GET':
        # return 登录    类似HttpResponse
        # return jsonify({'code': 0, 'msg': '登录成功'})   返回JSON格式响应
        return render_template('login.html')  # 默认是从templates文件夹找

    user = request.form.get('user')
    pwd = request.form.get('pwd')

    if user == 'admin' and pwd == '123456':  # 假设登录成功了吧
        return redirect('/index')

    return render_template('login.html', msg='用户名或密码错误')  # 登录失败,返回登录页面,并提示错误信息


@app.route('/index', endpoint='idx')  # 通过endpoint给路由命名
def index():
    data_dict = DATA_DICT
    return render_template('index.html', data_dict=data_dict)   # 登陆成功,返回首页


@app.route('/edit', methods=['GET', 'POST'])
def edit():
    if request.method == 'GET':
        nid = request.args.get('nid')  # 用request.args取数据
        nid = int(nid)
        info = DATA_DICT[nid]
        return render_template('edit.html', info=info)  # 到edit.html页面进行修改

    user = request.form.get('user')
    age = request.form.get('age')
    nid = request.args.get('nid')  # 获取url上的参数
    nid = int(nid)
    DATA_DICT[nid]["user"] = user
    DATA_DICT[nid]["age"] = age

    return redirect(url_for("idx"))  # 修改之后跳回首页


@app.route('/delete/<int:nid>', methods=['POST'])
def delete(nid):
    del DATA_DICT[nid]
    #return redirect('/index')   删除数据之后跳转回首页
    return redirect(url_for("idx"))  # 使用别名访问/index


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

总结

  • Flask路由是用装饰器写的
  • 路由参数有url, methods和endpoint。methods的默认值为['GET', ], endpoint的默认值为函数名,且endpoint不能重名。
  • 支持动态路由:@app.route('/index/<int:nid>')
  • 获取提交的数据:GET方法request.args, POST方法request.form
  • 返回数据: render_template('模板文件'), jsonify({}), redirect(url)

保存用户的会话信息

from flask import session

app = Flask(__name__)  
  
app.secret_key = "hrteMN9gnMwplaB2" # 随机字符串, 用于加密session


@app.route('/login', methods=['GET', 'POST'])  
def login():
    ...
    if user == 'admin' and pwd == '123456':  # 假设登录成功了吧
        session['user'] = "admin"  # session是保存用户登录状态的,Flask框架下保存于用户的浏览器中
        # 之后请求将session传入后被解密
        return redirect('/index')
    ...

@app.route('/index', endpoint='idx')  
def index():
    username = session.get('user')  # 取到解密后的session
    if not username:
        return redirect('/login')  # 如果session无值,则重新登录
    ...
...

装饰器实现用户认证

import functools
...
def auth(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        username = session.get('user')  # 取到解密后的session
        if not username:
            return redirect('/login')  # 如果session无值,则重新登录
        return func(*args, **kwargs)

    return inner
...
@app.route('/index', endpoint='idx')
@auth
def index():
    data_dict = DATA_DICT
    return render_template('index.html', data_dict=data_dict)  # 登陆成功,返回首页

蓝图(标准目录结构)