一文搞懂 Python Flask:快速入门
欢迎来到 Flask 的世界
Flask 是一个使用 Python 编写的轻量级 Web 应用框架。与 Django 这种“全能型”框架不同,Flask 被称为“微框架”(microframework),它只保留了构建 Web 应用最核心的功能,比如路由、请求处理、模板渲染等。这意味着 Flask 不强制要求使用特定的数据库、模板引擎或第三方库。它提供了极大的灵活性,开发者可以根据自己的需求自由选择和组合各种组件。
正因为其轻量和灵活,Flask 非常适合用于构建小型应用、API 服务、微服务原型或作为学习 Web 开发的入门工具。
本文将带你快速掌握 Flask 的核心概念,并构建一个简单的 Web 应用。
准备工作
在开始之前,你需要确保你的系统已经安装了 Python。推荐使用 Python 3.6 或更高版本。
为了更好地管理项目依赖,强烈建议使用虚拟环境 (Virtual Environment)。虚拟环境可以隔离项目所需的库,避免不同项目之间的依赖冲突。
-
创建虚拟环境:
打开终端或命令提示符,进入你的项目目录,然后运行:
bash
python -m venv venv
这会在当前目录下创建一个名为venv
的文件夹,里面包含了新的 Python 环境。 -
激活虚拟环境:
- 在 macOS 或 Linux 上:
bash
source venv/bin/activate - 在 Windows 命令提示符上:
bash
venv\Scripts\activate.bat - 在 Windows PowerShell 上:
powershell
venv\Scripts\Activate.ps1
激活后,你的终端提示符前会显示(venv)
字样。
- 在 macOS 或 Linux 上:
-
安装 Flask:
在激活的虚拟环境中,使用 pip 安装 Flask:
bash
pip install Flask
现在,你已经准备好开始编写第一个 Flask 应用了!
你的第一个 Flask 应用:”Hello, World!”
让我们从最经典的 “Hello, World!” 开始。创建一个名为 app.py
的文件,并输入以下代码:
“`python
导入 Flask 类
from flask import Flask
创建 Flask 应用实例
name 是一个特殊的 Python 变量,表示当前模块的名字。
Flask 用它来确定应用根目录的位置,以便找到静态文件和模板文件。
app = Flask(name)
使用装饰器定义路由
@app.route(‘/’) 将 URL “/” 映射到下面的函数
@app.route(‘/’)
def hello_world():
# 当访问 “/” 时,执行此函数并返回字符串作为响应
return ‘Hello, World!’
运行应用
只有在直接运行此脚本时(而不是作为模块导入时)才执行 app.run()
if name == ‘main‘:
# debug=True 模式在开发期间非常有用,它会在代码改动时自动重启服务器,
# 并在出错时提供交互式调试器。生产环境中应关闭 debug 模式。
app.run(debug=True)
“`
保存文件后,在终端(确保虚拟环境已激活)中运行:
bash
python app.py
你会看到类似以下的输出:
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
打开你的 Web 浏览器,访问 http://127.0.0.1:5000/
。你将看到页面显示 “Hello, World!”。恭喜,你成功运行了第一个 Flask 应用!
按下 Ctrl+C
可以停止服务器。
核心概念详解
基于上面的 “Hello, World!” 例子,我们来深入理解几个核心概念:
-
Flask
实例 (app = Flask(__name__)
):
这是你的 Flask Web 应用对象。你所有的路由、配置和扩展都将绑定到这个实例上。__name__
参数是必需的,它帮助 Flask 找到应用所在的位置,以便正确加载资源。 -
路由 (
@app.route('/')
):
路由是将特定的 URL 请求映射到 Python 函数的过程。在 Flask 中,这通常通过@app.route()
装饰器来实现。装饰器放在函数定义上方,告诉 Flask 当用户访问指定 URL(例如'/'
)时,应该执行哪个函数。 -
视图函数 (
def hello_world():
):
被路由装饰器关联的函数称为视图函数。当对应的 URL 被访问时,Flask 会调用这个函数。视图函数的返回值是发送给用户的响应,通常是 HTML 字符串、JSON 数据或一个完整的 Response 对象。 -
运行应用 (
app.run(debug=True)
):
app.run()
启动一个本地的开发服务器,监听指定的端口(默认是 5000)。在开发过程中设置debug=True
会开启调试模式,它提供两个便利功能:- 代码自动重载: 当你修改代码并保存时,服务器会自动重启。
- 交互式调试器: 当应用发生错误时,浏览器会显示一个交互式页面,你可以查看错误堆栈并执行 Python 代码来诊断问题。
-
if __name__ == '__main__':
:
这是一个标准的 Python 习惯用法。它确保app.run()
只在你直接运行app.py
文件时执行。如果这个文件被其他脚本作为模块导入,app.run()
不会被调用。这对于组织大型项目或进行单元测试非常有用。
添加更多路由和动态内容
一个 Web 应用通常不止一个页面。我们可以添加更多路由:
“`python
from flask import Flask
app = Flask(name)
@app.route(‘/’)
def index():
return ‘这是首页’
@app.route(‘/about’)
def about():
return ‘这是关于页面’
if name == ‘main‘:
app.run(debug=True)
“`
运行此代码,访问 http://127.0.0.1:5000/
会看到“这是首页”,访问 http://127.0.0.1:5000/about
会看到“这是关于页面”。
动态路由 (URL 变量)
很多时候,URL 中需要包含动态信息,比如用户 ID 或产品名称。Flask 允许你在路由中定义变量:
“`python
from flask import Flask
app = Flask(name)
@app.route(‘/’)
def index():
return ‘首页’
表示 URL 中的一个变量部分
@app.route(‘/user/
def show_user_profile(username):
# Flask 会将 URL 中的对应部分捕获,并作为同名参数传递给视图函数
return f’用户: {username}’
你也可以指定变量类型,例如 表示一个整数
@app.route(‘/post/
def show_post(post_id):
# post_id 会被自动转换为整数
return f’帖子 ID: {post_id}’
if name == ‘main‘:
app.run(debug=True)
“`
运行代码,访问 http://127.0.0.1:5000/user/张三
会显示 “用户: 张三”,访问 http://127.0.0.1:5000/post/123
会显示 “帖子 ID: 123″。如果访问 /post/abc
,Flask 会返回一个 404 错误,因为 abc
无法转换为整数。
使用模板 (Templates)
直接在 Python 代码中返回 HTML 字符串非常不灵活,特别是当 HTML 内容复杂或需要动态生成时。Flask 使用模板引擎来渲染 HTML 页面,默认是 Jinja2。
使用模板的好处是:
* 分离关注点: 将 Python 逻辑(视图函数)与 HTML 结构(模板)分开。
* 代码复用: 可以创建基础模板并继承,或者使用宏来重用 HTML 片段。
* 动态内容生成: 可以在模板中使用变量、循环、条件判断等逻辑来动态生成 HTML。
步骤如下:
-
创建
templates
文件夹: 在你的app.py
文件同级目录下创建一个名为templates
的文件夹。Flask 会自动在这个文件夹中查找模板文件。 -
创建模板文件: 在
templates
文件夹中创建一个 HTML 文件,例如index.html
:html
<!doctype html>
<html>
<head>
<title>Flask 示例</title>
</head>
<body>
<h1>欢迎, {{ name }}!</h1>
<p>这是一个使用 Flask 渲染的页面。</p>
</body>
</html>
注意{{ name }}
,这是 Jinja2 的语法,表示一个变量。视图函数会将名为name
的变量传递给模板,模板引擎会在渲染时将其替换为实际的值。 -
在视图函数中渲染模板: 修改
app.py
代码,导入render_template
函数,并在视图函数中使用它:“`python
from flask import Flask, render_template # 导入 render_templateapp = Flask(name)
@app.route(‘/’)
@app.route(‘/hello/‘) # 添加一个带有动态参数的路由
def hello(name=None):
# 调用 render_template 函数,指定模板文件名,并传递变量
# 如果访问的是 ‘/’ 路由,name 会是 None
return render_template(‘index.html’, name=name)添加一个简单的只渲染模板的路由
@app.route(‘/simple’)
def simple_page():
# 可以不传递变量,直接渲染静态模板
return render_template(‘simple.html’)if name == ‘main‘:
app.run(debug=True)
``
/simple
* 为了配合路由,你可以在
templates文件夹中再创建一个
simple.html` 文件,里面放一些简单的 HTML 内容。
运行代码:
* 访问 http://127.0.0.1:5000/
会显示 “欢迎, !” (因为 name 是 None)。
* 访问 http://127.0.0.1:5000/hello/小明
会显示 “欢迎, 小明!”。
* 访问 http://127.0.0.1:5000/simple
会显示 simple.html
的内容。
render_template
函数会自动查找 templates
文件夹中的指定文件,并使用传递的关键字参数作为模板中的变量进行渲染。
生成 URL (url_for
)
在模板或者 Python 代码中,经常需要生成指向其他页面的 URL。直接硬编码 URL (比如 /about
) 有一个缺点:如果将来你改变了某个路由的 URL (比如 /about
改成 /about-us
),你需要找到所有引用了这个 URL 的地方并修改。
Flask 提供了 url_for()
函数来解决这个问题。它根据视图函数的名称动态生成 URL。
例如,你有以下路由:
“`python
@app.route(‘/’)
def index():
pass # 假设这里渲染 index.html
@app.route(‘/login’)
def login():
pass # 假设这里渲染 login.html
“`
在模板 (index.html
) 中,你可以这样生成到 login 页面的链接:
“`html
“`
在 Python 代码中,你也可以使用 url_for()
来进行重定向等操作:
“`python
from flask import Flask, redirect, url_for
app = Flask(name)
@app.route(‘/’)
def index():
return ‘首页’
@app.route(‘/login’)
def login():
return ‘登录页面’
@app.route(‘/old-login’)
def old_login():
# 将旧的登录 URL 重定向到新的登录 URL
return redirect(url_for(‘login’))
if name == ‘main‘:
app.run(debug=True)
“`
访问 /old-login
会自动跳转到 /login
。
url_for()
的第一个参数是视图函数的名称(即 def
后面的函数名)。如果路由包含变量,你需要将变量值作为后续的关键字参数传递:
“`python
@app.route(‘/user/
def show_user_profile(username):
pass
在模板或代码中生成到特定用户页面的链接
url_for(‘show_user_profile’, username=’张三’) 会生成 ‘/user/张三’
“`
url_for
也常用于生成指向静态文件的 URL。默认情况下,Flask 会在项目根目录下的 static
文件夹中寻找静态文件(如 CSS、JavaScript、图片)。
例如,如果你有一个 static/style.css
文件,可以在模板中这样引入它:
html
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
这将生成类似于 /static/style.css
的 URL。
Request 对象基础
在 Web 应用中,经常需要获取用户请求中的信息,比如表单数据、URL 参数、请求头、HTTP 方法等。Flask 提供了 request
对象来访问这些信息。你需要从 flask
模块中导入它。
“`python
from flask import Flask, request
app = Flask(name)
@app.route(‘/’)
def index():
# 获取 URL 查询参数,例如访问 /?name=张三
name = request.args.get(‘name’, ‘访客’) # get() 方法带有默认值
return f’你好, {name}!’
@app.route(‘/login’, methods=[‘GET’, ‘POST’]) # 指定支持 GET 和 POST 方法
def login():
if request.method == ‘POST’:
# 如果是 POST 请求,从表单数据中获取用户名
# request.form 是一个字典,包含 POST 表单提交的数据
username = request.form.get(‘username’)
password = request.form.get(‘password’)
# 这里可以处理登录逻辑…
return f’收到 POST 请求,用户: {username}, 密码: {password}’
else:
# 如果是 GET 请求,显示一个简单的 HTML 表单
return ”’
”’
if name == ‘main‘:
app.run(debug=True)
“`
运行代码:
* 访问 http://127.0.0.1:5000/?name=李四
会显示 “你好, 李四!”。
* 访问 http://127.0.0.1:5000/login
(GET 请求) 会显示登录表单。
* 在表单中填写信息并提交 (POST 请求),页面会显示提交的数据。
request
对象提供了许多属性和方法来访问请求的各个方面:
* request.method
: 请求的 HTTP 方法(GET, POST 等)。
* request.args
: URL 中的查询参数(?key=value
),返回一个 Multidict。
* request.form
: POST 请求中的表单数据,返回一个 Multidict。
* request.cookies
: 浏览器发送的 cookie,返回一个字典。
* request.headers
: 请求头信息,返回一个 EnvironHeaders 对象。
* request.json
: 如果请求带有 Content-Type: application/json
头,此属性包含解析后的 JSON 数据。
* request.files
: 上传的文件,返回一个 Multidict。
通常,使用 get()
方法访问 request.args
和 request.form
中的数据更安全,因为即使键不存在也不会引发 KeyError 异常,而是返回 None
或你指定的默认值。
一个简单示例整合
让我们把路由、动态参数、模板和 url_for
结合起来,创建一个简单的问候应用。
项目结构:
my_greeting_app/
├── venv/
├── app.py
└── templates/
├── index.html
└── greeting.html
app.py
:
“`python
from flask import Flask, render_template, request, redirect, url_for
app = Flask(name)
@app.route(‘/’)
def index():
# 渲染首页模板
return render_template(‘index.html’)
@app.route(‘/greet’, methods=[‘POST’])
def greet_user():
# 处理 POST 请求,从表单获取用户名
username = request.form.get(‘username’)
if username:
# 如果用户名存在,重定向到 /hello/
return redirect(url_for(‘hello’, username=username))
else:
# 如果用户名为空,重定向回首页或显示错误
# 这里简单处理,重定向回首页
return redirect(url_for(‘index’))
@app.route(‘/hello/
def hello(username):
# 渲染问候页面模板,传递用户名变量
return render_template(‘greeting.html’, username=username)
if name == ‘main‘:
app.run(debug=True)
“`
templates/index.html
:
“`html
请输入你的名字
“`
templates/greeting.html
:
“`html
你好, {{ username }}!
很高兴认识你。
“`
运行 python app.py
,访问 http://127.0.0.1:5000/
。在输入框输入名字并提交,会跳转到 /hello/你的名字
页面,并显示个性化的问候。
这个例子展示了:
* 如何定义多个路由。
* 如何使用模板渲染不同的页面。
* 如何处理 POST 表单提交的数据 (request.form
)。
* 如何进行重定向 (redirect
)。
* 如何使用 url_for
安全地生成不同路由的 URL。
* 如何通过 URL 变量 (/hello/<username>
) 和模板传递数据。
下一步探索
通过本文,你已经掌握了 Flask 的基本使用,包括路由、视图函数、模板、请求处理和 URL 生成。这些是构建任何 Flask 应用的基础。
要进一步提升你的 Flask 技能,你可以探索以下主题:
- Flask 扩展 (Extensions): Flask 社区提供了大量的扩展来简化常见任务,比如数据库集成 (Flask-SQLAlchemy)、表单处理 (Flask-WTF)、用户认证 (Flask-Login)、RESTful API (Flask-RESTful) 等。
- 数据库集成: 学习如何将 Flask 应用连接到数据库(如 SQLite, PostgreSQL, MySQL),并使用 ORM (如 SQLAlchemy) 或其他库进行数据操作。
- Web 表单: 学习使用 Flask-WTF 等库更方便地创建、验证和处理 Web 表单。
- 部署: 如何将你的 Flask 应用部署到生产环境(如使用 Gunicorn, Nginx, Docker 或云服务平台)。
- 错误处理: 自定义 404、500 等错误页面。
- 蓝图 (Blueprints): 在大型应用中,使用蓝图可以将应用划分为更小的、可重用的模块。
- 上下文 (Contexts): 理解请求上下文和应用上下文是掌握 Flask 高级用法的关键。
总结
Flask 是一个优雅、灵活且易于上手的 Python Web 框架。它的微框架特性使得入门门槛较低,同时丰富的扩展生态使其能够胜任各种规模的项目。
通过本文的学习,你应该能够快速搭建并运行一个简单的 Flask 应用,理解其核心工作原理。这只是 Flask 世界的冰山一角,但足以让你迈出构建 Web 应用的第一步。
祝你在 Flask 的探索之旅中一切顺利!