共计 6730 个字符,预计需要花费 17 分钟才能阅读完成。
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 模型映射成表三步:
- flask db init:这步只需执行一次
- flask db migrate:识别 ORM 模型的改变,生成迁移脚本
- 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