用Flask从零搭建第一个Python网站:新手入门教程
本教程面向零基础开发者,系统讲解如何使用Python微框架Flask搭建第一个可交互的本地网站。内容涵盖虚拟环境配置、首个应用编写、URL路由与动态传参、Jinja2模板渲染、静态样式引入与常见报错排查。
一、认识 Flask 与 Web 工作机制
在 Python 的 Web 开发领域,Flask 被定义为“微框架”(Microframework)。这里的“微”并不意味着它的能力弱小,而是指它的核心极其紧凑:Flask 只负责最核心的 HTTP 请求分发、URL 路由映射以及模板渲染接口,而不强行捆绑数据库引擎、表单验证器或权限控制系统。开发者可以根据具体项目的需求按需添加组件,这种设计让初学者能够直观地看清 Web 应用的底层脉络,而不会被庞杂的框架规则所困扰。
当我们在浏览器地址栏输入一个网址并按下回车时,整个交互遵循标准的客户端-服务器(Client-Server)模型。浏览器将请求打包成 HTTP 协议文本发送给服务器,Flask 应用内部的 WSGI 适配网关(Werkzeug)接收到底层连接后,比对预先写好的路由规则,将请求分发给对应的 Python 函数进行处理。函数计算出结果或渲染 HTML 网页后,再将 HTTP 响应报文回传给浏览器完成呈现。
明确了这一流程后,搭建一个网站就可以拆解为三个最纯粹的任务:接收请求的 URL、用 Python 代码编写处理逻辑、以及返回正确的 HTML 网页内容。
二、准备工作:创建隔离虚拟环境与安装 Flask
在开始编写任何网站代码之前,首要步骤是为当前项目建立独立的虚拟环境(Virtual Environment)。如果在系统的全局 Python 环境中直接安装第三方包,当后续开发其他项目需要不同版本的依赖时,极易发生版本冲突。虚拟环境相当于在项目根目录下开辟了一个干净、独立的沙盒。
请打开你的终端(macOS/Linux 下的 Terminal,或 Windows 下的 PowerShell),依次执行以下命令:
1. 创建项目目录并初始化虚拟环境
# 创建项目文件夹并进入
mkdir my_flask_app
cd my_flask_app
# 使用 Python 内置的 venv 模块创建名为 venv 的虚拟环境
python3 -m venv venv
python 而非 python3,请将上述命令中的 python3 替换为 python。执行完成后,当前目录下会生成一个名为 venv/ 的文件夹,里面包含了独立的 Python 解释器与 pip 依赖包管理器。
2. 激活虚拟环境
虚拟环境创建后处于未激活状态,必须显式激活。不同操作系统的激活命令略有区别:
- macOS / Linux 系统:执行
source venv/bin/activate - Windows PowerShell:执行
.env\Scripts\Activate.ps1(若提示脚本执行策略受限,可在终端执行Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass后重试) - Windows CMD(命令提示符):执行
venv\Scriptsctivate.bat
当终端命令行的最左侧出现括号包裹的 (venv) 标识时,说明当前命令行会话已成功切换至独立沙盒环境。
3. 安装 Flask 依赖包
在已激活的虚拟环境中,直接使用 pip 安装 Flask:
pip install flask
可以通过以下单行命令验证 Flask 是否已正确安装及其当前版本:
python -c "import flask; print('Flask 版本:', flask.__version__)"
三、编写第一个最小可用 Flask 应用
在 my_flask_app 目录下,新建一个名为 app.py 的文件。这是 Flask 应用的默认入口文件。请使用代码编辑器打开它,写入以下完整代码:
# 导入 Flask 核心类
from flask import Flask
# 创建 Flask 应用实例
# __name__ 是 Python 内置变量,代表当前模块的名称,Flask 用它来确定根路径以便定位模板和静态文件
app = Flask(__name__)
# 使用装饰器声明路由规则
# 当用户访问网站根路径 '/' 时,执行下方的 index 函数
@app.route('/')
def index():
return 'Hello, World! 这是我的第一个 Flask 网站。'
# 确保脚本被直接运行时才启动开发服务器
if __name__ == '__main__':
# 启动本地开发服务器,监听本地 5000 端口,开启 debug 模式
app.run(host='127.0.0.1', port=5000, debug=True)
逐行理解核心代码的作用
Flask(__name__):构建 Web 应用的核心实例对象。一切路由注册、错误捕获和配置项都围绕这个app对象展开。@app.route('/'):Python 装饰器语法,将 HTTP 请求的 URL 路径与下方的视图函数(View Function)建立绑定关系。这里的'/'代表网站的根首页。def index(): return '...':当匹配到根路径请求时执行该函数。返回值将由 Flask 自动包装为 HTTP 200 OK 响应报文,并作为网页正文发送给浏览器。app.run(debug=True):启动 Flask 自带的简易 Web 开发服务器。开启debug=True后,修改代码保存即可自动热重载,且报错时会在终端与页面上提供详尽的异常堆栈。
运行并验证首个页面
在激活了虚拟环境的终端中,运行该脚本:
python app.py
此时开发服务器已经成功监听本地的 5000 端口。打开你的任意浏览器,在地址栏输入 http://127.0.0.1:5000 并回车。你将在浏览器窗口中清晰地看到纯文本内容:Hello, World! 这是我的第一个 Flask 网站。 这表明你的第一个 Python Web 应用程序已经正常工作。在终端中按下快捷键 Ctrl + C 即可停止运行。
四、掌握 Web 核心:URL 路由与动态参数传递
真实的网站绝不可能只有一个根页面。Flask 提供了极其直观的路由注册方式,不仅支持多页面静态路径,还支持从 URL 中动态提取变量。
我们修改 app.py,增加几个不同的路由示例:
from flask import Flask
app = Flask(__name__)
# 1. 静态路由:关于页面
@app.route('/about')
def about():
return '这是一个使用 Flask 从零搭建的演示网站。'
# 2. 动态路由:字符串参数
# <username> 会将该段 URL 捕获并作为参数传入视图函数
@app.route('/user/<username>')
def show_user(username):
return f'欢迎访问用户个人主页:{username}'
# 3. 动态路由带类型转换器:整数参数
# <int:post_id> 确保只有纯数字能匹配该路由,并自动转换为 int 类型传入函数
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'正在阅读第 {post_id} 篇文章,下篇 ID 为 {post_id + 1}'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000, debug=True)
Flask 内置 URL 转换器对照
| 转换器语法 | 匹配规则与类型 | 典型示例与匹配结果 |
|---|---|---|
<variable_name> |
默认转换器(string),接收不含斜杠 / 的任何字符串 |
/user/zhangsan ➔ 'zhangsan' |
<int:variable_name> |
正整数转换器,非数字将直接触发 404 Not Found | /post/1024 ➔ 1024(整型数值) |
<float:variable_name> |
浮点数转换器,匹配带有小数点的数值 | /rate/3.14 ➔ 3.14(浮点型数值) |
<path:variable_name> |
路径转换器,类似 string 但允许包含目录斜杠 / |
/files/docs/readme.txt ➔ 'docs/readme.txt' |
保存文件后,由于开启了 debug=True,Flask 会检测到代码变更并自动重启服务。在浏览器分别访问 http://127.0.0.1:5000/about、http://127.0.0.1:5000/user/alex 和 http://127.0.0.1:5000/post/88,即可看到动态拼接生成的不同响应。
五、规范工程结构:分离 HTML 模板与 Jinja2 渲染
在实际生产中,直接在 Python 函数中返回拼接的 HTML 字符串会导致代码极其混乱且无法维护。为了遵循“关注点分离”的工程规范,我们需要将 Python 业务逻辑与 HTML 页面结构拆分开来。
Flask 约定了标准的项目目录规范:所有 HTML 网页模板必须存放在项目根目录下的 templates/ 文件夹内;所有 CSS 样式、JavaScript 脚本与图片等静态资源必须存放在 static/ 文件夹内。
1. 创建 templates 目录与 HTML 模板
在项目根目录 my_flask_app 下新建 templates 文件夹,并在该文件夹下新建 index.html:
mkdir templates
编写 templates/index.html 文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ page_title }}</title>
<!-- 引入静态资源样式表 -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<div class="container">
<header class="header">
<h1>{{ site_name }}</h1>
<p class="subtitle">欢迎,<strong>{{ current_user }}</strong>!你已成功渲染 Jinja2 模板。</p>
</header>
<main class="content">
<h2>今日学习清单</h2>
<ul class="task-list">
{# 使用 Jinja2 循环语句遍历 Python 传来的列表 #}
{% for item in learning_tasks %}
<li class="task-item">
<span class="badge">已完成</span>
<span class="text">{{ item }}</span>
</li>
{% else %}
<li>当前暂无待办项目。</li>
{% endfor %}
</ul>
</main>
</div>
</body>
</html>
{{ 表达式 }}:变量插值语法,用于将 Python 变量输出到 HTML 中并自动执行安全转义。{% 语句 %}:控制结构语法,用于书写if...else分支判断与for...in循环遍历。{# 注释 #}:模板注释,渲染为最终 HTML 时会被直接剔除,不会泄露给前端用户。
2. 更新 app.py 调用 render_template
从 flask 模块中额外导入 render_template 函数,将数据作为关键字参数传入:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
# 准备要在页面中展示的业务数据
context = {
'page_title': '首页 - 我的第一个 Flask 网站',
'site_name': 'Python Flask 学习工作台',
'current_user': '初学者小陈',
'learning_tasks': [
'创建并激活 venv 独立虚拟环境',
'理解 WSGI 请求响应流程与轻量架构',
'使用 @app.route 注册多级与动态路由',
'利用 Jinja2 模板引擎实现前后端解耦',
'组织 static 静态资源与排查常见异常'
]
}
# 渲染 templates/index.html,并将 context 字典打散传入
return render_template('index.html', **context)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000, debug=True)
六、美化网站:引入 CSS 与静态资源
为了让网站拥有现代美观的外观,我们需要为它添加样式。Flask 强制规定静态资源存放在 static/ 目录下。
1. 创建 static 静态资源目录与样式文件
在项目根目录下创建层级文件夹:
# 创建 static/css 目录
mkdir -p static/css
编写 static/css/style.css 样式文件:
/* 全局重置与基础设定 */
body {
margin: 0;
padding: 40px 20px;
background-color: #FAFAF7;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
color: #2D3748;
}
.container {
max-width: 720px;
margin: 0 auto;
background: #FFFFFF;
border-radius: 12px;
padding: 32px 40px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
border: 1px solid #E2E8F0;
}
.header {
border-bottom: 2px solid #EDF2F7;
padding-bottom: 20px;
margin-bottom: 24px;
}
h1 {
margin: 0 0 8px 0;
color: #6487A5;
font-size: 26px;
}
.subtitle {
margin: 0;
color: #718096;
font-size: 14.5px;
}
h2 {
font-size: 18px;
margin-bottom: 16px;
color: #2D3748;
}
.task-list {
list-style: none;
padding: 0;
margin: 0;
}
.task-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: #F7FAFC;
border-radius: 8px;
margin-bottom: 10px;
border: 1px solid #EDF2F7;
}
.badge {
background-color: #C28B68;
color: #FFFFFF;
font-size: 12px;
font-weight: 600;
padding: 2px 8px;
border-radius: 4px;
}
.text {
font-size: 14.5px;
color: #4A5568;
}
href="static/css/style.css" 相对路径。一旦路由变为多层(例如 /user/alex/posts),相对路径就会失效变成 /user/alex/static/css/style.css 从而导致 404 样式丢失。使用 Flask 提供的 url_for('static', filename='...'),系统会自动生成基于根路径的绝对引用地址(如 /static/css/style.css),保证在任何复杂 URL 下样式均能准确加载。
保存代码后,重新打开浏览器刷新 http://127.0.0.1:5000,原本简陋的白底黑字页面瞬间变成了一个拥有精致排版、圆角卡片、柔和蓝橙配色的现代化完整网页。
七、新手常见报错与排错清单
在初次搭建 Flask 网站的过程中,遇到报错是非常正常的现象。以下整理了新手最常见的四大问题及其精准排查方案:
1. 端口占用报错:Address already in use (Errno 48 / 10048)
报错表现:终端启动时提示 OSError: [Errno 48] Address already in use 或 WinError 10048。
产生原因:5000 端口已被其他程序占用。在 macOS Monterey 及以上系统中,系统自带的“隔空播放接收器”(AirPlay Receiver)默认监听 5000 端口;或者上次运行的 Python 进程未完全退出。
解决方法:在 app.run() 中将端口更改为未被占用的端口号,例如 5001 或 8080:
app.run(host='127.0.0.1', port=5001, debug=True)
2. 模板文件找不到:jinja2.exceptions.TemplateNotFound: index.html
报错表现:浏览器出现 Internal Server Error,终端抛出 TemplateNotFound: index.html。
产生原因:Flask 严格要求模板文件夹名称为 templates(复数形式,带 s)。如果拼写成 template 或将 HTML 文件误放在与 app.py 同级而未建文件夹,Flask 将无法定位模板。
排查核对:在终端执行 ls -d templates,确保当前工作目录下存在名为 templates 的文件夹,且目标文件位于其内部。
3. 访问出现 404 Not Found
产生原因:输入的 URL 路径与 @app.route() 声明的规则不匹配。需要特别注意末尾斜杠规则:
- 若路由定义为
@app.route('/about/')(带末尾斜杠),访问/about时 Flask 会自动重定向至/about/。 - 若路由定义为
@app.route('/about')(不带末尾斜杠),访问/about/则会直接返回 404 Not Found。
4. 导入报错:ModuleNotFoundError: No module named 'flask'
产生原因:在执行 python app.py 时,当前终端并没有激活前面创建的虚拟环境,导致使用的是未安装 Flask 的系统默认全局解释器。
解决方法:检查终端命令行左侧是否有 (venv) 标记。如果没有,重新执行 source venv/bin/activate(或 Windows 对应的激活命令)后再启动脚本。
debug=True 会启用 Werkzeug 交互式网页调试器。当代码发生异常时,页面会展示完整的上下文代码变量,并允许在浏览器端输入 PIN 码直接执行任意 Python 脚本。这在本地开发时是极为高效的排错利器,但在公网服务器上开启将造成致命的安全漏洞。发布上线时必须将 debug 设为 False,并使用 Gunicorn 或 uWSGI 等生产级 WSGI 服务器提供服务。
八、总结与进阶学习路径
至此,你已经完成了第一个 Python Flask 网站的完整搭建。从创建干净的独立虚拟环境开始,我们理解了轻量微框架的核心理念,编写了最小可用应用,掌握了 URL 动态路由映射,并通过分离 templates/ 与 static/ 实现了规范的工程解耦与前端美化。
搭建出能通过浏览器访问的静态展示页面只是 Web 开发的第一步。若想让你的网站具备真正的业务实用价值,建议按照以下路线继续深入探索:
- 处理用户表单提交(POST 请求):学习从
flask模块中引入request对象,使用request.form接收用户在 HTML 表单中输入的账号密码或搜索关键词。 - 接入数据库持久化:利用 Python 原生自带的
sqlite3模块或安装Flask-SQLAlchemy,将用户发布的内容、留言或文章存储到数据库中,让网页内容实现持久化保留。 - 用户身份验证与 Session:学习使用
session记录用户的登录态,区分管理员与普通访客权限。 - 模块化架构与生产交付:当路由与页面增多时,利用 Flask 蓝图(Blueprint)将大项目拆分为多个独立子模块,最终配合 Gunicorn 和 Nginx 部署至 Linux 云服务器。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









