Flask 是 Python 的一个轻量级 Web 框架,因其灵活性和易用性而广受欢迎。本文将详细介绍 Flask 的基础配置、路由规则、模板引擎、请求处理、会话控制以及 ORM 数据库操作等核心功能。
一、项目初始化
使用 PyCharm 自动创建项目或手动创建均可。推荐的标准目录结构如下:
├── app.py
├── config.py
├── exts.py
├── models.py
├── /
└── templates/
本文详细介绍了 Python Flask 框架的快速入门与核心应用。内容涵盖项目初始化、路由规则(含参数与正则)、响应处理(HTML/JSON/重定向)、Jinja2 模板引擎的使用、请求数据获取、会话控制(Cookie 与 Session)以及基于 SQLAlchemy 的 ORM 数据库操作。此外,文章还补充了数据库迁移工具的使用方法及安全与最佳实践建议,适合希望快速掌握 Flask Web 开发的开发者参考。

Flask 是 Python 的一个轻量级 Web 框架,因其灵活性和易用性而广受欢迎。本文将详细介绍 Flask 的基础配置、路由规则、模板引擎、请求处理、会话控制以及 ORM 数据库操作等核心功能。
使用 PyCharm 自动创建项目或手动创建均可。推荐的标准目录结构如下:
├── app.py
├── config.py
├── exts.py
├── models.py
├── /
└── templates/
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "hello world"
if __name__ == '__main__':
app.run()
创建 Flask 实例时,可自定义以下配置参数:
| 参数 | 说明 |
|---|---|
static_path | 静态文件访问路径(不推荐使用,建议使用 static_url_path) |
static_url_path | 指定静态文件的访问路径(默认为 /static) |
static_folder | 存放静态文件资源的文件夹名称(默认为 static) |
template_folder | 存放模板的文件夹名称(默认为 templates) |
@app.route('/')
def hello_world():
return "hello world"
@app.route("/user/<username>")
def user_info(username):
return "hello %s" % username
@app.route("/user/<string:username>")
def user_info(username):
return "hello %s" % username
注: 转换器类型包括
string,int,float,uuid,path等。
在 Flask 中不能直接使用 re 模块,需通过自定义转换器实现。步骤如下:
BaseConverter。BaseConverter)。url_map.converters 字典中。from flask import Flask, render_template
from werkzeug.routing import BaseConverter
app = Flask(__name__)
class RegexConverter(BaseConverter):
def __init__(self, url_map, *args):
super(RegexConverter, self).__init__(url_map)
self.regex = args[0]
app.url_map.converters['re'] = RegexConverter
@app.route("/user/<re('lcz.{2}'):username>")
def user_info(username):
return "hello %s" % username
@app.route('/')
def index():
return render_template("index.html")
if __name__ == '__main__':
app.run()
系统自带转换器:
default: UnicodeConverterpath: PathConverterstring: UnicodeConverterany: AnyConverterint: IntegerConverterfloat: FloatConverteruuid: UUIDConverter使用 methods 参数限定请求方法,注意 methods 应为列表。
from flask import request
@app.route("/user", methods=["GET", "POST"])
def user():
if request.method == "GET":
return "user get"
elif request.method == "POST":
return "user post"
else:
return "method not allowed"
@app.route("/user")
def user():
return "<h1>User Info</h1>"
from flask import render_template
@app.route('/')
def hello_world():
return render_template("index.html")
from flask import jsonify
@app.route("/user")
def user():
data = {
"user_name": "lczmx",
"age": 18
}
return jsonify(data)
from flask import redirect, url_for
@app.route("/index")
def index():
return redirect("/")
from flask import redirect, url_for
@app.route("/user/<int:user_id>")
def user(user_id):
if user_id > 200:
return redirect(url_for("vip_user", user_id=user_id))
else:
return redirect(url_for("general_user"))
@app.route("/vip_user/<int:user_id>")
def vip_user(user_id):
return "vip_user %s" % user_id
@app.route("/general_user")
def general_user():
return "general_user"
@app.route('/')
def index():
return render_template("index.html"), 200
Flask 默认使用 Jinja2 模板引擎,语法与 Django 相似。
使用 {{ 变量名 }} 输出。
@app.route('/')
def index():
return render_template("index.html", name="嘻嘻嘻")
使用 {# 多行注释 #}。
使用 {{ var|filter }}。
{{ data.bool|default('我是默认值', boolean=True) }}{{ '<em>hello</em>' | safe }}{{ '<em>hello</em>' | striptags }}{{ 'hello' | capitalize }}{{ 'HELLO' | lower }}{{ 'hello' | reverse }}{{ 'hello world' | truncate(5) }}{{ [1,2,3,4] | join('') }}{{ [1,2,3,4,5,6] | length }}{{ [1,2,3,4,5,6] | sum }}{{ [6,2,3,1,5,4] | sort }}方法 1:通过 Flask 对象添加
def add_suffix(line):
return line + "--嘻嘻嘻"
app.add_template_filter(add_suffix, 'add_suffix')
方法 2:使用装饰器
@app.template_filter()
def add_suffix(line):
return line + "--嘻嘻嘻"
{% if user_info.nid == 10 %}
<li>{{ user_info.msg1 }}</li>
{% elif user_info.nid == 20 %}
<li>{{ user_info.msg2 }}</li>
{% else %}
<li>{{ user_info.msg3 }}</li>
{% endif %}
{% for name in name_list %}
<li>{{ name }}</li>
{% endfor %}
注: 不支持
continue和break。可使用loop关键字查看迭代状态。
| 属性 | 说明 |
|---|---|
index0 | 当前迭代的索引 (从 0 开始) |
index | 当前迭代的索引 (从 1 开始) |
first | 是否为第一次迭代 |
last | 是否为最后一次迭代 |
length | 数据长度 |
导入: {% include "layout.html" %}
继承:
base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% block title %}{% endblock %}
<div>
<h1>今天是个好日子</h1>
</div>
{% block content %}
<h3>我是内容</h3>
{% endblock %}
{% block js %}
<script src="../static/js/jquery.js"></script>
{% endblock %}
</body>
</html>
index.html:
{% extends "base.html" %}
{% block title %}
<h1>啦啦啦</h1>
{% endblock %}
{% block js %}
{% endblock %}
需先导入 request:from flask import request。
| 属性名 | 说明 |
|---|---|
request.scheme | 获取请求协议 |
request.method | 获取请求方式 (GET / POST) |
request.args | 获取 GET 请求提交的数据 |
request.form | 获取 POST 请求提交的数据 |
request.cookies | 获取 Cookie 信息 |
request.headers | 获取请求头信息 |
request.files | 获取上传的文件 |
request.path | 获取资源路径 (不带参数) |
request.full_path | 获取完整路径 (带参数) |
request.url | 获取完整地址 |
注:
request.args,request.form,request.files的返回值均为字典。
Cookie 由服务器生成发送给客户端,浏览器保存并在下次请求时发送。建议不存储敏感信息。
from flask import make_response
@app.route('/set_cookie')
def set_cookie():
res = make_response('set cookie page')
res.set_cookie('username', 'lczmx', max_age=604800)
return res
from flask import request
@app.route('/vip')
def resp_cookie():
user_name = request.cookies.get('username')
if user_name == "lczmx":
return "vip"
else:
return "bye"
Session 存储在服务器端,依赖 Cookie。使用 Flask Session 需配置 SECRET_KEY。
生成随机密钥:
import os
print(os.urandom(24))
config.py:
CSRF_ENABLED = True
SECRET_KEY = '你的随机密钥'
app.py:
import config
app.config.from_object(config)
from flask import session
@app.route('/set_session')
def set_session():
session['username'] = 'xxx'
session['password'] = '123456'
return 'success'
from flask import session, jsonify
@app.route('/login')
def login():
user_name = session.get('username')
pass_word = session.get('password')
if user_name == "xxx" and pass_word == "123456":
return jsonify({"status": 1, "msg": "success"})
else:
return jsonify({"status": 0, "msg": "failed"})
Flask 通常配合 Flask-SQLAlchemy 使用。
pip install flask-sqlalchemy
pip install pymysql # MySQL 驱动
exts.py:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
config.py:
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'test'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
username=USERNAME, password=PASSWORD, host=HOST, port=PORT, db=DATABASE
)
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
app.py:
from flask import Flask
import config
from exts import db
app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)
models.py:
from exts import db
class User(db.Model):
__tablename__ = "User"
uid = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
注意: 类必须继承 db.Model。在 app.py 中导入模型文件才能创建表。
from models import User
db.create_all() # 必须在视图函数中调用
新增:
user_obj = User(username='test', email='[email protected]')
db.session.add(user_obj)
db.session.commit()
查询:
# 查询所有
users = User.query.all()
# 根据 ID 查询
user = User.query.get(1)
# 过滤查询
users = User.query.filter(User.username.startswith('l')).all()
# 分页
page = User.query.paginate(page=1, per_page=10, error_out=False)
修改:
user = User.query.get(1)
user.username = 'new_name'
db.session.commit()
删除:
user = User.query.get(1)
db.session.delete(user)
db.session.commit()
主表定义 relationship,子表定义 ForeignKey。
class User(db.Model):
__tablename__ = 'user'
nid = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(16), nullable=False)
articles = db.relationship("Article", backref="author")
class Article(db.Model):
__tablename__ = 'Article'
nid = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(36), nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey("user.nid"))
注意: ForeignKey 参数为 表名。字段名。
需定义关联表。
student_course = db.Table('student_course',
db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('course.id')))
class Student(db.Model):
__tablename__ = 'student'
id = db.Column(db.Integer, primary_key=True)
courses = db.relationship('Course', secondary=student_course)
class Course(db.Model):
__tablename__ = 'course'
id = db.Column(db.Integer, primary_key=True)
使用 flask-migrate 管理版本。
pip install flask-migrate
from flask_migrate import Migrate
migrate = Migrate(app, db)
命令行操作:
flask db init
flask db migrate -m "initial migration"
flask db upgrade
建议将配置放入 config.py 或使用环境变量。生产环境应隐藏 SECRET_KEY。
@app.errorhandler(404)
def not_found(error):
return "Page Not Found", 404
@app.errorhandler(500)
def internal_error(error):
return "Internal Server Error", 500
CSRF_ENABLED = True)。debug=True)。随着项目规模扩大,建议采用应用工厂模式(Application Factory),将 create_app() 函数封装,便于测试和部署。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online