用 Flask 搭个 Todo List:从 0 到 1 学会轻量级 Web 开发

目录

引言:Web框架中的一股“清流”

一、为什么 Flask 值得学?先搞懂它的 “轻量哲学”

二、环境搭建:3 步搞定 Flask 开发环境(附避坑指南)

步骤 1:安装 Python(已安装可跳过)

步骤 2:创建虚拟环境(关键!避免版本冲突)

步骤 3:安装 Flask

三、5 行代码跑通第一个 Flask 应用:Hello World 实战

步骤 1:创建主程序文件

步骤 2:启动应用,查看效果

四、核心概念拆解:用 “餐厅” 类比理解 Flask 工作流

五、实战 Todo List:从需求到代码的完整实现

阶段 1:用列表存储数据(快速原型)

步骤 1:定义路由和视图函数

步骤 2:创建 HTML 模板(展示页面)

步骤 3:测试功能

阶段 2:用数据库持久化存储(SQLAlchemy)

步骤 1:安装 Flask-SQLAlchemy

步骤 2:配置数据库,定义模型

步骤 3:模板无需修改,直接测试

阶段 3:优化用户体验(表单验证 + 闪现消息)

步骤 1:安装 Flask-WTF

步骤 2:配置密钥,创建表单类

步骤 3:修改模板,显示表单和闪现消息

六、Flask 扩展生态:按需添加功能(推荐清单)

七、部署上线:让你的 Todo List 能被别人访问

简易部署步骤(以 Linux 服务器为例):

八、常见问题与避坑指南(新手必看)

九、学习资源推荐:从入门到进阶

总结:Flask 的学习路径与核心优势


 

class 卑微码农:
    def __init__(self):
        self.技能 = ['能读懂十年前祖传代码', '擅长用Ctrl+C/V搭建世界', '信奉"能跑就别动"的玄学']
        self.发量 = 100  # 初始发量
        self.咖啡因耐受度 = '极限'
        
    def 修Bug(self, bug):
        try:
            # 试图用玄学解决问题
            if bug.严重程度 == '离谱':
                print("这一定是环境问题!")
            else:
                print("让我看看是谁又没写注释...哦,是我自己。")
        except Exception as e:
            # 如果try块都救不了,那就...
            print("重启一下试试?")
            self.发量 -= 1  # 每解决一个bug,头发-1
 
 
# 实例化一个我
我 = 卑微码农()

引言:Web框架中的一股“清流”

如果你问我:“想快速开发一个 Web 应用,又不想被复杂的框架束缚,该选什么工具?” 我的答案一定是 Flask。

作为 Python 生态里最 “轻” 的 Web 框架之一,Flask 就像一个灵活的乐高积木套装 —— 它只提供最核心的功能,剩下的都交给你自己搭配。这种 “极简主义” 让它成为新手入门 Web 开发的绝佳选择,也让老开发者能快速搭建原型。

今天这篇文章,我会带着你从零开始,用 Flask 开发一个能上线的 Todo List(待办事项)应用。全程不扯晦涩概念,只讲实战技巧,代码可直接复用,哪怕是刚接触 Python 的新手也能跟着做。

一、为什么 Flask 值得学?先搞懂它的 “轻量哲学”

第一次用 Flask 时,我最惊讶的是:一个能跑起来的 Web 应用,居然只需要 5 行代码

相比 Django 那种 “自带电池” 的全功能框架(什么都给你安排好,但也限制了灵活性),Flask 更像一个 “毛坯房”—— 它只提供路由、模板渲染这两个核心功能,剩下的数据库、表单验证、用户认证等功能,你可以按需选择扩展。

这种设计带来两个明显好处:

  • 学习成本低:不用一上来就记一堆概念,先掌握核心逻辑,再逐步扩展;
  • 灵活性高:比如数据库,你可以用 SQLite 快速开发,也能换成 MySQL/PostgreSQL;想加用户系统,装个 Flask-Login 就行,不用改框架本身。

简单说:Flask 让你 “用多少学多少”,不会让新手在一开始就被复杂的配置吓退。这也是为什么很多初创公司用它做 MVP(最小可行产品),以及开发者用它快速验证想法。

二、环境搭建:3 步搞定 Flask 开发环境(附避坑指南)

开始写代码前,先把环境搭好。这里以 “Windows 10+Python 3.9” 为例,macOS 和 Linux 操作类似,最后会说明差异。

步骤 1:安装 Python(已安装可跳过)

Flask 是 Python 框架,首先得装 Python。去官网(https://www.python.org/)下载对应版本,注意安装时一定要勾选 “Add Python to PATH”(否则后面会报 “python 不是内部命令” 的错),然后一路 “Next” 完成安装。

验证是否安装成功:按下Win+R,输入cmd打开命令提示符,输入python --version,能看到 “Python 3.9.x” 就说明没问题。

步骤 2:创建虚拟环境(关键!避免版本冲突)

为什么要搞虚拟环境?举个例子:你之前用 Django 3.2 做了个项目,现在学 Flask 需要装 Flask 2.3,直接装会可能冲突。虚拟环境能给每个项目单独隔离一套依赖,互不影响。

操作步骤:

  1. 找个地方建个项目文件夹,比如D:\flask_todo
  2. 打开 cmd,用cd命令进入这个文件夹:cd D:\flask_todo
  3. 输入命令创建虚拟环境:python -m venv venv(最后一个venv是环境名,随便起);
  4. 激活虚拟环境:
    • Windows:输入venv\Scripts\activate,激活后命令行前会出现(venv)
    • macOS/Linux:输入source venv/bin/activate

注意:如果 Windows 激活时提示 “无法运行脚本”,是因为系统安全策略限制,解决方法:

  1. 右键 “开始”→ 打开 “Windows PowerShell(管理员)”;
  2. 输入Set-ExecutionPolicy RemoteSigned,选 “Y” 确认;
  3. 重新用 PowerShell 进入项目文件夹激活虚拟环境。

步骤 3:安装 Flask

在虚拟环境激活的状态下,直接用 pip 安装:pip install flask==2.3.3(指定 2.3.3 版本,稳定且文档全)。

验证安装:输入flask --version,显示 “Flask 2.3.3” 就说明成功了。

小技巧:安装后可以输入pip freeze > requirements.txt,把当前环境的依赖保存到文件里,以后换电脑时直接pip install -r requirements.txt就能一键安装所有依赖。

三、5 行代码跑通第一个 Flask 应用:Hello World 实战

环境就绪后,我们先来个最简单的例子,感受下 Flask 的 “轻量”。

步骤 1:创建主程序文件

flask_todo文件夹下(和venv同级),新建一个app.py文件,内容如下:

# 导入Flask类
from flask import Flask

# 创建Flask应用实例,__name__是当前模块名,Flask会用它找静态文件和模板
app = Flask(__name__)

# 定义路由:当访问根路径(/)时,执行hello函数
@app.route('/')
def hello():
    return 'Hello Flask! 这是我的第一个应用~'

# 如果直接运行这个文件,就启动服务器
if __name__ == '__main__':
    app.run(debug=True)  # debug=True表示开启调试模式,改代码后自动重启

步骤 2:启动应用,查看效果

在 cmd 中(确保虚拟环境已激活,且在flask_todo目录下),输入python app.py,会看到类似这样的输出:

 * Serving Flask app 'app'
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

打开浏览器访问http://127.0.0.1:5000/,就能看到页面上显示 “Hello Flask! 这是我的第一个应用~”。

调试模式的好处:现在试着修改return后面的文字(比如改成 “Flask 真简单!”),保存后不用重启服务器,刷新浏览器就能看到变化,开发效率翻倍。

四、核心概念拆解:用 “餐厅” 类比理解 Flask 工作流

刚才的例子虽然简单,但已经包含了 Flask 的核心逻辑。我们用 “餐厅” 来类比,帮你理解它的工作流程:

  • app = Flask(__name__):相当于开了一家餐厅,app就是餐厅的 “营业执照”,负责管理整个应用;
  • @app.route('/'):相当于餐厅的 “门牌号”,告诉客人 “从这个入口进来,能吃到特定的菜”;
  • def hello(): return ...:相当于 “厨师”,客人(用户)从指定门牌号(路由)进来后,厨师(视图函数)就做出对应的菜(返回响应内容);
  • app.run():相当于 “开门营业”,启动服务器接收客人(用户)的请求。

整个流程就是:用户访问某个 URL → Flask 根据路由找到对应的视图函数 → 视图函数处理并返回内容 → 用户看到结果。

五、实战 Todo List:从需求到代码的完整实现

接下来我们开发一个实用的 Todo List 应用,包含这些功能:

  • 显示所有待办事项;
  • 添加新的待办事项;
  • 标记事项为 “已完成”;
  • 删除待办事项。

我们会分阶段实现,从简单到复杂,每一步都能看到效果。

阶段 1:用列表存储数据(快速原型)

先用 Python 列表在内存中存储待办事项,不涉及数据库,快速实现核心功能,感受 Flask 的路由和模板用法。

步骤 1:定义路由和视图函数

修改app.py,添加展示列表、添加事项、标记完成、删除事项的逻辑:

from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)

# 用列表存储待办事项,每个事项是字典:id唯一标识,content内容,done是否完成
todos = [
    {'id': 1, 'content': '学习Flask', 'done': False},
    {'id': 2, 'content': '写一篇技术博客', 'done': False}
]
next_id = 3  # 下一个事项的id(模拟自增主键)

# 首页:展示所有待办事项
@app.route('/')
def index():
    # 把todos列表传给模板,模板中用{{ todos }}就能拿到数据
    return render_template('index.html', todos=todos)

# 添加新事项:接收表单提交的数据
@app.route('/add', methods=['POST'])  # 只允许POST方法(表单提交通常用POST)
def add_todo():
    global next_id  # 使用全局变量next_id
    content = request.form.get('content')  # 获取表单中name为content的值
    if content:  # 确保内容不为空
        todos.append({'id': next_id, 'content': content, 'done': False})
        next_id += 1
    # 重定向到首页(避免刷新页面时重复提交表单)
    return redirect(url_for('index'))

# 标记事项为已完成
@app.route('/done/<int:todo_id>')  # <int:todo_id>表示从URL中获取整数类型的id
def done_todo(todo_id):
    for todo in todos:
        if todo['id'] == todo_id:
            todo['done'] = not todo['done']  # 切换状态(完成→未完成,反之亦然)
            break
    return redirect(url_for('index'))

# 删除事项
@app.route('/delete/<int:todo_id>')
def delete_todo(todo_id):
    global todos
    # 过滤掉id为todo_id的事项(相当于删除)
    todos = [todo for todo in todos if todo['id'] != todo_id]
    return redirect(url_for('index'))

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

这里用到了几个新东西:

  • render_template:渲染 HTML 模板(把数据传给 HTML 页面);
  • request:获取用户提交的数据(比如表单内容);
  • redirecturl_for:重定向到其他页面(url_for('index')会生成index视图对应的 URL);
  • 动态路由/done/<int:todo_id>:从 URL 中提取参数(比如访问/done/1todo_id就是 1)。

步骤 2:创建 HTML 模板(展示页面)

Flask 默认会从templates文件夹读取模板,所以先在flask_todo下创建templates文件夹,然后在里面新建index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Flask Todo List</title>
    <style>
        /* 简单美化样式 */
        body {
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
            font-family: "微软雅黑", sans-serif;
        }
        h1 {
            color: #333;
            text-align: center;
        }
        .add-form {
            margin-bottom: 30px;
            text-align: center;
        }
        input[type="text"] {
            width: 70%;
            padding: 8px;
            font-size: 16px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        button {
            padding: 8px 16px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }
        button:hover {
            background: #45a049;
        }
        .todo-list {
            list-style: none;
            padding: 0;
        }
        .todo-item {
            padding: 10px;
            margin-bottom: 10px;
            background: #f9f9f9;
            border-radius: 4px;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }
        .todo-content {
            flex: 1;
            margin: 0 10px;
        }
        .done .todo-content {
            text-decoration: line-through;
            color: #888;
        }
        .delete-btn {
            background: #f44336;
        }
        .delete-btn:hover {
            background: #d32f2f;
        }
    </style>
</head>
<body>
    <h1>我的待办事项</h1>

    <!-- 添加新事项的表单:提交到/add路由,用POST方法 -->
    <form class="add-form" action="{{ url_for('add_todo') }}" method="post">
        <input type="text" name="content" placeholder="输入新的待办事项..." required>
        <button type="submit">添加</button>
    </form>

    <!-- 待办事项列表 -->
    <ul class="todo-list">
        {% for todo in todos %}
        <li class="todo-item {% if todo.done %}done{% endif %}">
            <!-- 标记完成/未完成的链接 -->
            <a href="{{ url_for('done_todo', todo_id=todo.id) }}">
                {% if todo.done %}✓{% else %}○{% endif %}
            </a>
            <span class="todo-content">{{ todo.content }}</span>
            <!-- 删除链接 -->
            <a href="{{ url_for('delete_todo', todo_id=todo.id) }}">
                <button class="delete-btn">删除</button>
            </a>
        </li>
        {% else %}
        <li>暂无待办事项,添加一个吧!</li>
        {% endfor %}
    </ul>
</body>
</html>

模板里的{{ }}{% %}是 Jinja2 模板引擎的语法(Flask 默认用它):

  • {{ url_for('add_todo') }}:生成add_todo视图对应的 URL(这里是/add);
  • {% for todo in todos %}:循环遍历todos列表,显示每个事项;
  • {% if todo.done %}done{% endif %}:条件判断,如果事项已完成,就添加done类(用于 CSS 样式)。

步骤 3:测试功能

启动应用python app.py,访问http://127.0.0.1:5000/,试试这些操作:

  • 在输入框添加新事项,点击 “添加”;
  • 点击事项前的 “○”,标记为已完成(变成 “✓” 且文字划线);
  • 点击 “删除” 按钮,移除事项。

注意:因为数据存在内存里,一旦重启服务器,所有新增 / 修改的事项都会消失。接下来我们用数据库解决这个问题。

阶段 2:用数据库持久化存储(SQLAlchemy)

实际开发中,数据需要存在数据库里。Flask 本身不自带 ORM,但可以用Flask-SQLAlchemy扩展(这就是 Flask 的灵活性:想用什么装什么)。

步骤 1:安装 Flask-SQLAlchemy

在虚拟环境中输入:pip install flask-sqlalchemy==3.1.1

步骤 2:配置数据库,定义模型

修改app.py,用 SQLAlchemy 替代列表存储数据:

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy  # 导入扩展
from datetime import datetime  # 用于记录时间

app = Flask(__name__)

# 配置数据库:SQLite数据库文件存放在项目根目录的todo.db
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 关闭不必要的警告

# 初始化数据库
db = SQLAlchemy(app)

# 定义Todo模型(对应数据库表)
class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)  # 主键,自增
    content = db.Column(db.String(200), nullable=False)  # 事项内容,不允许为空
    done = db.Column(db.Boolean, default=False)  # 是否完成,默认未完成
    created_time = db.Column(db.DateTime, default=datetime.now)  # 创建时间

    def __repr__(self):
        return f'<Todo {self.id}>'  # 调试时显示的内容

# 创建数据库表(首次运行时需要)
with app.app_context():
    db.create_all()

# 首页:查询所有事项,按创建时间倒序
@app.route('/')
def index():
    # Todo.query.all() 获取所有事项,order_by按创建时间倒序
    todos = Todo.query.order_by(Todo.created_time.desc()).all()
    return render_template('index.html', todos=todos)

# 添加新事项
@app.route('/add', methods=['POST'])
def add_todo():
    content = request.form.get('content')
    if content:
        # 创建新事项对象
        new_todo = Todo(content=content)
        db.session.add(new_todo)  # 添加到会话
        db.session.commit()  # 提交到数据库
    return redirect(url_for('index'))

# 标记完成/未完成
@app.route('/done/<int:todo_id>')
def done_todo(todo_id):
    todo = Todo.query.get_or_404(todo_id)  # 获取事项,不存在则返回404
    todo.done = not todo.done
    db.session.commit()  # 保存修改
    return redirect(url_for('index'))

# 删除事项
@app.route('/delete/<int:todo_id>')
def delete_todo(todo_id):
    todo = Todo.query.get_or_404(todo_id)
    db.session.delete(todo)  # 删除
    db.session.commit()
    return redirect(url_for('index'))

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

这里的核心是Todo模型,它对应数据库中的todo表:

  • db.Column定义字段,db.Integer是整数类型,db.String(200)是字符串(最长 200 字符);
  • primary_key=True表示该字段是主键;
  • nullable=False表示不允许为空(确保事项有内容)。

with app.app_context(): db.create_all()的作用是创建数据库表,首次运行时会在项目根目录生成todo.db文件。

步骤 3:模板无需修改,直接测试

重启服务器后访问首页,之前的测试数据会消失(因为用了新数据库),但现在添加的事项会被永久保存,重启服务器也不会丢失。

小技巧:如果想查看数据库内容,可以用 SQLite 浏览器(比如 “DB Browser for SQLite”)打开todo.db文件,直观地看到表结构和数据。

阶段 3:优化用户体验(表单验证 + 闪现消息)

现在的应用有个问题:如果用户在添加事项时输入空内容,虽然服务器会忽略,但用户看不到提示。我们用Flask-WTF做表单验证,并添加 “闪现消息”(临时提示)。

步骤 1:安装 Flask-WTF

输入命令:pip install flask-wtf==1.2.1

步骤 2:配置密钥,创建表单类

修改app.py,添加表单验证逻辑:

from flask import Flask, render_template, request, redirect, url_for, flash  # 新增flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm  # 导入表单基类
from wtforms import StringField, SubmitField  # 导入字段类型
from wtforms.validators import DataRequired  # 导入验证器(确保不为空)
from datetime import datetime
import os

app = Flask(__name__)

# 配置密钥:用于加密表单数据(生产环境要换成复杂的随机字符串)
app.config['SECRET_KEY'] = os.urandom(24)  # 生成随机密钥
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 定义Todo模型(同上,不变)
class Todo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)
    done = db.Column(db.Boolean, default=False)
    created_time = db.Column(db.DateTime, default=datetime.now)

    def __repr__(self):
        return f'<Todo {self.id}>'

# 创建表单类
class TodoForm(FlaskForm):
    content = StringField('待办事项', validators=[DataRequired(message='内容不能为空哦~')])
    submit = SubmitField('添加')

with app.app_context():
    db.create_all()

@app.route('/', methods=['GET', 'POST'])  # 首页同时支持GET和POST(接收表单提交)
def index():
    form = TodoForm()  # 创建表单实例
    if form.validate_on_submit():  # 如果表单提交且验证通过
        content = form.content.data  # 获取表单数据
        new_todo = Todo(content=content)
        db.session.add(new_todo)
        db.session.commit()
        flash('添加成功!', 'success')  # 闪现成功消息
        return redirect(url_for('index'))
    
    # 获取所有事项
    todos = Todo.query.order_by(Todo.created_time.desc()).all()
    return render_template('index.html', todos=todos, form=form)  # 把表单传给模板

# 标记完成和删除的视图不变,省略...

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

这里的关键变化:

  • TodoForm类:定义表单字段和验证规则,DataRequired确保内容不为空;
  • flash('消息内容', '类别'):用于发送临时消息(比如操作成功 / 失败提示);
  • 首页路由添加methods=['GET', 'POST'],直接在首页处理表单提交(更合理)。

步骤 3:修改模板,显示表单和闪现消息

更新templates/index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Flask Todo List</title>
    <style>
        /* 保留之前的样式,新增闪现消息样式 */
        .flash-messages {
            margin: 20px 0;
            padding: 10px;
            border-radius: 4px;
        }
        .success {
            background: #dff0d8;
            color: #3c763d;
        }
        .error {
            background: #f2dede;
            color: #a94442;
        }
        .form-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }
        .invalid-feedback {
            color: #a94442;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <h1>我的待办事项</h1>

    <!-- 显示闪现消息 -->
    {% with messages = get_flashed_messages(with_categories=true) %}
      {% if messages %}
        <div class="flash-messages">
          {% for category, message in messages %}
            <div class="{{ category }}">{{ message }}</div>
          {% endfor %}
        </div>
      {% endif %}
    {% endwith %}

    <!-- 使用WTForms渲染表单 -->
    <form class="add-form" method="post">
        {{ form.csrf_token }}  <!-- 防止CSRF攻击,必须加 -->
        <div class="form-group">
            {{ form.content.label }}
            {{ form.content(size=50, placeholder="输入新的待办事项...") }}
            <!-- 显示验证错误信息 -->
            {% if form.content.errors %}
              {% for error in form.content.errors %}
                <div class="invalid-feedback">{{ error }}</div>
              {% endfor %}
            {% endif %}
        </div>
        {{ form.submit() }}
    </form>

    <!-- 待办事项列表(不变) -->
    <ul class="todo-list">
        {% for todo in todos %}
        <li class="todo-item {% if todo.done %}done{% endif %}">
            <a href="{{ url_for('done_todo', todo_id=todo.id) }}">
                {% if todo.done %}✓{% else %}○{% endif %}
            </a>
            <span class="todo-content">{{ todo.content }}</span>
            <a href="{{ url_for('delete_todo', todo_id=todo.id) }}">
                <button class="delete-btn">删除</button>
            </a>
        </li>
        {% else %}
        <li>暂无待办事项,添加一个吧!</li>
        {% endfor %}
    </ul>
</body>
</html>

模板变化:

  • {{ form.csrf_token }}:必须添加,用于防止跨站请求伪造攻击;
  • {% with messages = get_flashed_messages(...) %}:显示闪现消息(成功 / 错误提示);
  • 表单字段用{{ form.content() }}渲染,自动包含验证逻辑。

现在测试:

  • 提交空内容,会显示 “内容不能为空哦~” 的错误提示;
  • 正常添加事项,会显示 “添加成功!” 的成功提示。

六、Flask 扩展生态:按需添加功能(推荐清单)

Flask 的强大之处在于丰富的扩展,像搭积木一样给应用加功能。除了前面用的Flask-SQLAlchemyFlask-WTF,这些扩展也很常用:

  1. Flask-Login快速实现用户认证(登录 / 注册 / 登出),支持记住密码、保护路由(必须登录才能访问)。比如给 Todo List 加用户系统,让每个人只能看到自己的事项。

  2. Flask-Bootstrap集成 Bootstrap 前端框架,不用自己写 CSS 就能让页面变美观。用法简单:from flask_bootstrap import Bootstrap,然后Bootstrap(app),模板中继承bootstrap/base.html即可。

  3. Flask-Migrate数据库迁移工具,当修改模型(比如给Todo加个priority字段)时,不用删除旧表,直接用命令更新数据库结构,保留已有数据。

  4. Flask-Caching给应用加缓存,减少数据库查询次数,提高性能。比如缓存热门页面的内容,适合访问量较大的应用。

  5. Flask-Admin快速生成后台管理界面,类似 Django Admin,但更轻量。只需几行代码,就能创建一个可管理数据库的后台。

七、部署上线:让你的 Todo List 能被别人访问

开发完成后,怎么让别人也能访问你的应用?我们可以把它部署到云服务器(比如阿里云、腾讯云,学生有优惠)。

简易部署步骤(以 Linux 服务器为例):

  1. 服务器安装依赖

    # 安装Python和pip
    sudo apt update
    sudo apt install python3 python3-pip python3-venv
    
  2. 上传代码scp命令或 FTP 工具(如 FileZilla)把项目文件传到服务器(比如/home/ubuntu/flask_todo)。

  3. 创建虚拟环境并安装依赖

    cd /home/ubuntu/flask_todo
    python3 -m venv venv
    source venv/bin/activate
    pip install -r requirements.txt  # 之前保存的依赖文件
    pip install gunicorn  # 生产环境用的WSGI服务器
    
  4. 修改app.py的启动方式去掉debug=True(生产环境禁用调试模式),添加:

    if __name__ == '__main__':
        app.run()  # 只保留这一行
    
  5. 用 Gunicorn 启动应用

    gunicorn -w 4 -b 0.0.0.0:8000 'app:app'  # 4个工作进程,监听8000端口
    
  6. 配置 Nginx(可选,推荐)作为反向代理,处理静态文件并转发动态请求到 Gunicorn,提高性能和安全性。

部署后,别人通过服务器的 IP 地址就能访问你的 Todo List 了。

八、常见问题与避坑指南(新手必看)

  1. “TemplateNotFound” 错误原因:模板文件路径不对。Flask 默认找项目根目录/templates/下的文件,确保文件名和路径正确(比如templates/index.html)。

  2. 表单提交报 400 错误原因:忘记加{{ form.csrf_token }}。Flask-WTF 默认启用 CSRF 保护,必须在表单中添加这个字段。

  3. 数据库操作报 “working outside of application context”原因:在 Flask 应用上下文之外操作数据库。解决方法:用with app.app_context():包裹数据库操作代码(比如创建表时)。

  4. 闪现消息不显示原因:没配置SECRET_KEY。闪现消息需要密钥加密,必须在app.config中设置SECRET_KEY

  5. 部署后静态文件不加载原因:生产环境需要单独配置静态文件路径。可以用app.config['STATIC_FOLDER']指定,或通过 Nginx 处理静态文件。

九、学习资源推荐:从入门到进阶

如果想深入学习 Flask,这些资源亲测好用:

总结:Flask 的学习路径与核心优势

回顾整个开发过程,我们从 5 行代码的 Hello World,到一个带数据库、表单验证、用户提示的 Todo List,只用了不到 200 行代码。这就是 Flask 的魅力 ——它不强迫你用什么,而是让你选择需要什么

对于新手,我的学习建议是:

  1. 先掌握核心概念(路由、视图、模板),用render_templaterequest做个简单页面;
  2. 学习Flask-SQLAlchemy操作数据库,理解 ORM 的基本用法;
  3. 按需学习扩展(表单、用户认证等),逐步完善应用;
  4. 最后尝试部署上线,体验从开发到发布的完整流程。

比起 “大而全” 的框架,Flask 更像一个 “引路人”—— 它让你在实践中理解 Web 开发的核心逻辑,而不是死记硬背框架的规则。当你能用 Flask 独立开发一个小应用时,再学其他框架(比如 Django)会轻松很多。

祝你在 Flask 的学习路上,用最少的代码,实现最多的想法!

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值