Python轻量级Web应用框架Flask学习笔记

编程 · 2023-12-29 · 196 人浏览

Flask

是一个基于Python实现的Web开发微框架(基于MVC设计模式),官方文档:https://flask.palletsprojects.com/en/3.0.x/

安装Flask:pip install flask

查看Flask版本:pip show flask

插件

Flask-SQLAlchemy

Flask-SQLAlchemy是对SQLAlchemy的一个封装,使得在Flask中使用SQLAlchemy更加方便。因为 Flask-SQLAlchemy依赖SQLAlchemy,所以只要安装了Flask-SQLAlchemy,SQLAlchemy会自动安装。

安装命令:pip install flask-sqlalchemy

Flask想要操作数据库,必须要先安装Python操作MySQL驱动,这里选用pymysql作为驱动程序,安装命令:pip install pymysql

Flask-Migrate

Flask-Migrate是处理Flask应用程序SQLAlchemy数据库迁移的扩展。

安装命令:pip install flask-migrate

数据库操作可通过Flask命令行界面进行,ORM模型映射成表三步:

  1. flask db init:这步只需执行一次
  2. flask db migrate:识别ORM模型的改变,生成迁移脚本
  3. flask db upgrade:运行迁移脚本,同步到数据库中

Flask-Mail

在Flask中可使用Flask-Mail发送邮箱验证码。

安装命令:pip install flask-mail

Flask-WTF

Flask-WTF是简化WTForms操作的第三方库。WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板,而Flask-WTF还包括一些其他的功能:CSRF保护,文件上传等。

安装Flask-WTF默认也会安装WTForms,安装命令:pip install flask-wtf

run参数

from flask import Flask

app = Flask(__name__)

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

if __name__ == "__main__":
    app.run(debug=True)
  • debug:是否开启调试模式,开启后(默认关闭),修改保存Python代码后会自动重启,方便调试
  • port:指定服务器端口号,默认是5000
  • host:主机,默认是127.0.0.1,指定为0.0.0.0代表所有ip

返回值

返回字符串

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "<h1>Home</h1>"  # 1. 返回 字符串,支持HTML标签

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

返回JSON

from flask import Flask
import json

app = Flask(__name__)

@app.route("/")
def index():
    data = {"name": "张三", "age": 18}
    response = app.response_class(
        response=json.dumps(data, ensure_ascii=False),  # ensure_ascii设置为False,避免出现中文乱码
        status=200,
        mimetype="application/json",
    )
    return response

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

若返回数据不包含中文:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def index():
    return jsonify({"name": "jack", "age": 18})

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

模板渲染

templates\index.html文件:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>首页</title>
    <link rel="stylesheet" href="{{ url_for('static',filename='index.css')}}" />
  </head>
  <body>
    <h2>{{name}}</h2>
  </body>
</html>

static\index.css文件:

h2 {
  color: red;
}

app.py文件:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    return render_template("index.html", name="张三")

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

自定义Response对象

from flask import Flask, make_response

app = Flask(__name__)

@app.route("/")
def index():
    html = "<h1>Home</h1>"
    res = make_response(html, 200)
    return res

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

也可以使用Flask的响应对象类Response,它允许更灵活地创建和自定义响应对象,以满足特定需求。对于更复杂的自定义响应,使用Response类会更有优势。

重定向

from flask import Flask, redirect

app = Flask(__name__)

@app.route("/")
def index():
    return redirect("https://www.baidu.com/")
    # return redirect("/home/")  # 也可以这么用

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

url_for反向解析,通过视图函数发过来找路由,url_for("蓝图名称.视图函数名")。

from flask import Flask, redirect, Blueprint, url_for

app = Flask(__name__)

blue = Blueprint("user", __name__)

@blue.route("/response/")
def get_response():
    return "response ok"

@blue.route("/")
def index():
    ret = url_for("user.get_response")
    return redirect(ret)

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

url_for也能传参:url_for("user.get_response", name="张三", age=18)。

请求Request

服务器在接收到客户端的请求后,Flask框架会自动创建Request对象,Request对象不可修改。属性有:

  • url 完整请求地址
  • base_url 去掉GET参数的URL
  • host_url 只有主机和端口号的URL
  • path 路由中的路径
  • method 请求方法
  • remote_addr 请求的客户端地址
  • args GET请求参数
  • form POST请求参数
  • files 文件上传
  • headers 请求头
  • cookies 请求中的cookie

类字典结构对象,获取指定key值:dict.get('key')和dict.getlist('key')。

路由参数

string

@app.route("/string/<name>/")
def get_name(name):
    return name

int

@app.route("/int/<int:id>/")
def get_int(id):
    return str(id)

float

@app.route("/float/<float:pi>/")
def get_float(pi):
    return str(pi)

path

支持/的字符串,例如/path/3/14/,返回3/14。

@app.route("/path/<path:name>/")
def get_path(name):
    return str(name)

uuid

@app.route("/get-uuid/")
def get_uuid():
    import uuid
    return str(uuid.uuid4())

@app.route("/uuid/<uuid:id>/")
def uuid(id):
    return str(id)

any

从列出的项目中选择一个。

@app.route("/any/<any(apple,orange, banana):fruit>/")
def get_any(fruit):
    return str(fruit)

项目拆分

Project
|   app.py
|
\---App
    |   models.py
    |   views.py
    |   __init__.py
    |
    +---static
    |       index.css
    |
    +---templates
    |       index.html

cookie

App\templates\index.html文件:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>首页</title>
    <link rel="stylesheet" href="{{ url_for('static',filename='index.css')}}" />
  </head>
  <body>
    <h2>首页</h2>
    <hr />
    {% if username %}
    <p>当前登录用户:{{username}} <a href="/logout/">注销</a></p>
    {% else %}
    <a href="/login/">登录</a>
    {% endif %}
  </body>
</html>

App\templates\login.html文件:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>登录</h2>
    <hr />

    <form action="" method="post">
      <p>用户名:<input type="text" name="username" /></p>
      <p>密码:<input type="password" name="password" /></p>
      <p><button>提交</button></p>
    </form>
  </body>
</html>

App\views.py文件:

import datetime
from flask import Blueprint, request, render_template, redirect
from .models import *

# 创建蓝图
blue = Blueprint("user", __name__)

@blue.route("/")
def index():
    # 4. 获取cookie
    username = request.cookies.get("user")
    return render_template("index.html", username=username)

@blue.route("/login/", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return render_template("login.html")
    elif request.method == "POST":
        # 1. 获取前端提交过来的数据
        username = request.form.get("username")
        password = request.form.get("password")

        # 2. 模拟登录:用户名和密码验证
        if username == "admin" and password == "123":
            response = redirect("/")

            # 3. 设置cookie
            response.set_cookie("user", username)  # 浏览器关闭失效
            # response.set_cookie("user", username, max_age=3600 * 24)  # 过期时间 秒
            # response.set_cookie(
            #     "user", username, expires=datetime.datetime(2023, 12, 31)
            # )

            return response
        else:
            return "用户名或密码错误!"

@blue.route("/logout/")
def logout():
    response = redirect("/")
    # 5. 删除cookie
    response.delete_cookie("user")

    return response

session

App\views.py文件:

import datetime
from flask import Blueprint, request, render_template, redirect, session
from .models import *

# 创建蓝图
blue = Blueprint("user", __name__)

@blue.route("/")
def index():
    # 4. 获取session
    username = session.get("user")
    return render_template("index.html", username=username)

@blue.route("/login/", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return render_template("login.html")
    elif request.method == "POST":
        # 1. 获取前端提交过来的数据
        username = request.form.get("username")
        password = request.form.get("password")

        # 2. 模拟登录:用户名和密码验证
        if username == "admin" and password == "123":
            response = redirect("/")

            # 3. 设置session
            session["user"] = username
            session.permanent = True

            return response

        else:
            return "用户名或密码错误!"

@blue.route("/logout/")
def logout():
    response = redirect("/")
    # 5. 删除session
    session.pop("user")
    # session.clear()  # 慎用,会删除所有session

    return response

还需要配置session,App\__init__.py文件:

import datetime
from flask import Flask
from .views import blue

def create_app():
    app = Flask(__name__)
    # 注册蓝图
    app.register_blueprint(blueprint=blue)

    # session配置
    # print(app.config)  # Flask配置信息
    app.config["SECRET_KEY"] = "abc123"
    app.config["PERMANENT_SESSION_LIFETIME"] = datetime.timedelta(days=3)

    return app
Python Flask
Theme Jasmine by Kent Liao