ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

零基础入门Flask:从零搭建一个可运行的Web应用

零基础入门Flask:从零搭建一个可运行的Web应用

简介:这是一份面向Python Web开发初学者的Flask入门实践项目,以“试验楼小Demo”的形式呈现一个简易博文系统,涵盖用户登录登出、博文发布与查看等核心功能,适合刚接触Flask、希望从零跑通一个完整Web应用流程的读者练手。压缩包共8个文件,约5KB,包含1个py主程序、1个pyc编译文件、3个html模板、1个css样式表,以及1个sql建表脚本和1个db数据库文件,结构精简,便于对照理解路由、模板渲染与数据存储的对应关系。资源已有3088人学习下载,说明其作为入门范例具备一定参考价值。项目虽小,却串联起Flask框架、SQLite3嵌入式数据库、session身份验证、Jinja2模板渲染与表单处理等Web开发基本要素,读者可借此熟悉模型表结构设计、视图函数编写与错误处理思路,是理解Flask项目组织方式的轻量样本。

1. 零基础也能跑起来的 Flask 小实验:先搞懂它到底是个啥

很多新手一听到“Web 开发”四个字,脑子里立刻浮现出服务器、部署、并发、数据库集群这些词,还没开始学就先把自己劝退了。其实你可以换个角度想:Web 开发就像开一家小饭馆,前端是门面和菜单,后端是后厨和仓库。Flask 就是给你一套现成的后厨设备——灶台、案板、冰箱都摆好了,你只需要往里放食材、写菜谱,不用自己从打地基开始盖房子。这份“自己敲的试验楼小 Demo”就是一间已经搭好骨架的小店,你进去照着做一遍,就能明白一家店是怎么运转起来的。

它解决的问题很具体:让你用 Python 写几行代码,就能在浏览器里看到一个真实页面,点一下按钮还能把数据存进数据库再读出来。适合谁?适合刚学完 Python 基础语法、想找个东西练手却不知道从哪下手的人;适合想看看“网页背后到底发生了什么”的好奇者;也适合那些被框架文档吓退过、需要一个能跑通的最小例子来建立信心的人。这份资源用的是 Flask 加 sqlite3,轻量、不用装一堆东西,一台普通电脑就能从头玩到尾。

2. 为什么值得先学 Flask:从“能跑”到“敢改”的心理门槛

2.1 轻量框架对新手到底友好在哪

新手学技术最怕什么?不是难,是“看不见反馈”。你背了一堆概念,敲了半天代码,结果连个页面都出不来,挫败感立刻拉满。Flask 最大的好处就是反馈快。一个路由、一个函数、一行返回,浏览器刷新就能看到结果。这种即时反馈对建立手感极其重要,就像学做菜先炒个鸡蛋,而不是一上来就做满汉全席。

对比那些大而全的框架,Flask 不强制你按它的规矩组织目录,不要求你先理解一堆配置文件。你可以从一个文件开始,慢慢加功能,加着加着自然就理解了什么是路由、什么是模板、什么是请求和响应。这份 Demo 的价值就在这儿:它是一栋“试验楼”,结构简单到你能一眼看穿,但又包含了 Web 应用最核心的几个部件——页面展示、表单提交、数据存取。你把它跑通一遍,再去看那些复杂的项目,心里就有底了。

2.2 一个 Demo 里藏着哪些真实开发环节

别看它叫“小 Demo”,麻雀虽小五脏俱全。一个能用的 Web 应用,哪怕再简单,也绕不开这几件事:接收用户的访问请求、返回对应的页面、把用户填的数据存起来、下次再打开还能看到。这份试验楼 Demo 把这几个环节都串了一遍,用的是 Flask 加 sqlite3 这套组合。

sqlite3 是 Python 自带的轻量数据库,不需要你单独安装数据库服务,一个文件就是一个库。对新手来说,这省掉了“装数据库、配账号密码、连不上”这一大串血泪经验。你写几行 SQL 就能建表、插入、查询,数据就实实在在落在你电脑的一个文件里。等你把这个流程走通了,再去换 MySQL 或者别的数据库,会发现只是连接方式变了,核心思路一模一样。这就是为什么建议从这个小组合入手:它把干扰项降到最低,让你专注在“请求进来、数据出去”这条主线上。

2.3 先跑通再理解,顺序别搞反

我见过太多新手卡在一个误区里:非要先把 Flask 的源码或者所有参数背下来才肯动手。结果书翻了三分之一,代码一行没写,热情先耗光了。正确的顺序恰恰相反——先让一个最小例子跑起来,看到页面,再回头问“为什么这行代码能生效”。

这份 Demo 就是为“先跑通”准备的。你不需要提前理解什么是 WSGI、什么是上下文,照着步骤把环境装好、文件建好、代码敲进去,浏览器里出现那个页面,你就已经跨过了最难的第一道坎。后面再去查文档、看教程,你会发现那些术语突然变得有落脚点了,因为你有具体的画面可以对应。学习这件事,有时候就是得先“知其然”,再慢慢“知其所以然”。

3. 动手前的准备:环境搭好,心里不慌

3.1 装 Python 和 Flask,两步搞定

第一步,确认你电脑上有 Python。打开终端(Windows 用命令提示符或 PowerShell,Mac 和 Linux 用终端),输入下面这行:

python --version

如果显示的是 Python 3.x 的版本号,说明已经有了。如果没有,去 Python 官网下载安装包,安装时记得勾选“Add Python to PATH”这个选项,不然终端里会找不到命令。装完之后再跑一次上面的命令确认。

第二步,装 Flask。在终端里输入:

pip install flask

这行命令的意思是让 pip 这个包管理工具去网上把 Flask 以及它依赖的几个小库下载下来装好。装完之后可以用pip show flask看一眼版本信息,有输出就说明成功了。这里有个小提醒:如果你电脑上同时有多个 Python 版本,pip 可能装到了另一个版本里,遇到“装了却导入不了”的情况,换成python -m pip install flask再试一次,这个写法能保证装到当前 python 对应的环境里。

3.2 建一个干净的项目文件夹

别把代码随手扔在桌面上。新建一个文件夹,名字随意,比如叫flask_demo,以后所有文件都放这里面。这样做的好处是路径清晰,不会出现“文件明明在却找不到”的玄学问题。进入这个文件夹,后面所有命令都在这个目录下执行。

mkdir flask_demo cd flask_demo

这两行就是建目录再进去。听起来简单,但新手翻车的高发区就在这儿:终端当前所在的目录和你以为的不一样,导致运行时报“找不到文件”。养成习惯,每次敲命令前先看一眼终端提示符里的路径对不对。

3.3 第一个能跑的页面:五行代码的事

在项目文件夹里新建一个文件,叫app.py,把下面这段敲进去:

from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "试验楼开张了" if __name__ == "__main__": app.run(debug=True)

逐行说一下。第一行从 flask 库里把 Flask 这个类拿进来。第二行创建了一个应用实例,__name__是 Python 给每个文件自动带的变量,Flask 靠它知道去哪里找模板和静态文件。第三行的@app.route("/")是一个装饰器,意思是“当有人访问根路径时,交给下面这个函数处理”。index函数返回一段文字,这段文字就会出现在浏览器里。最后两行是启动开关,debug=True表示开启调试模式,改了代码会自动重启,出错时页面上会显示详细信息,对新手排查问题非常有用。

保存文件,在终端里运行:

python app.py

你会看到终端输出一个本地地址,通常是http://127.0.0.1:5000。把它复制到浏览器打开,页面上出现“试验楼开张了”几个字。到这一步,你已经完成了一个 Web 应用最核心的闭环:浏览器发请求,Python 接住并返回内容。别小看这几行,后面所有的功能都是在这个骨架上长出来的。

4. 把试验楼盖起来:页面、表单和数据库三件套

4.1 用模板把页面和数据分开

上一步我们直接在函数里返回字符串,页面简单还行,稍微复杂一点就乱套了。真实开发里,页面结构放在模板文件里,数据由 Python 传进去。Flask 默认去项目下的templates文件夹找模板。新建一个文件夹叫templates,在里面建一个index.html:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>试验楼</title> </head> <body> <h1>欢迎来到试验楼</h1> <p>当前留言数:{{ count }}</p> </body> </html>

注意那个双大括号{{ count }},它是模板的占位符,Python 传什么它就显示什么。然后改app.py,把返回字符串换成渲染模板:

from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): return render_template("index.html", count=0) if __name__ == "__main__": app.run(debug=True)

render_template的作用就是找到模板文件、把变量填进去、生成最终 HTML 返回给浏览器。count=0就是传给模板的数据。刷新页面,你会看到“当前留言数:0”。这一步的意义在于建立了“数据驱动页面”的思维:页面长什么样是模板的事,显示什么数字是 Python 的事,两边各管各的,改起来互不干扰。

4.2 建一张表,让数据真正存下来

页面能显示了,但数据还是写死的。接下来让用户提交的内容真正存进数据库。用 sqlite3,在app.py里加一段初始化数据库的代码:

import sqlite3 def init_db(): conn = sqlite3.connect("demo.db") conn.execute("CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY, content TEXT)") conn.commit() conn.close()

sqlite3.connect("demo.db")会连接一个叫demo.db的文件,文件不存在就自动创建。CREATE TABLE IF NOT EXISTS的意思是表不存在才建,重复运行不会报错。messages表有两个字段:id是自增主键,content存留言内容。commit()是提交,不写这句数据不会真正落盘,这是新手最容易漏的一步。close()把连接关掉,养成好习惯。

在启动应用之前调用一次init_db(),表就建好了。你可以用 sqlite3 命令行或者任意数据库查看工具打开demo.db看看,表结构一目了然。数据从内存里的变量变成了硬盘上的文件,这是质的变化——关掉程序再打开,数据还在。

4.3 表单提交到入库,走通一条完整链路

现在把“提交留言”这条链路补全。在index.html里加一个表单:

<form action="/add" method="post"> <input type="text" name="content" placeholder="写点什么"> <button type="submit">提交</button> </form>

action="/add"表示提交到/add这个地址,method="post"表示用 POST 方式发送。然后在app.py里加对应的处理函数:

from flask import request, redirect @app.route("/add", methods=["POST"]) def add(): content = request.form.get("content", "").strip() if content: conn = sqlite3.connect("demo.db") conn.execute("INSERT INTO messages (content) VALUES (?)", (content,)) conn.commit() conn.close() return redirect("/")

request.form.get("content")取出表单里 name 为 content 的输入值,.strip()去掉首尾空格,空内容就不入库。INSERT INTO ... VALUES (?)里的问号是参数占位符,后面用元组把实际值传进去,这种写法能防止 SQL 注入,别图省事用字符串拼接。最后redirect("/")让浏览器跳回首页,避免用户刷新时重复提交。把首页的count改成真实查询:

@app.route("/") def index(): conn = sqlite3.connect("demo.db") count = conn.execute("SELECT COUNT(*) FROM messages").fetchone()[0] conn.close() return render_template("index.html", count=count)

fetchone()取第一行结果,[0]取第一列,也就是总数。现在刷新页面、填内容、点提交,数字会跟着变。一条从浏览器到 Python 再到数据库再回到浏览器的完整链路,你已经亲手走通了。

5. 新手最容易翻车的几个地方:排查清单

5.1 页面报 404,说找不到地址

现象是浏览器显示“Not Found”,终端里也有一行 404 的记录。原因通常是访问的路径和代码里@app.route写的路径对不上,比如代码写的是/add,你访问的是/add/,多一个斜杠在 Flask 里就是两个不同的地址。解决办法是仔细核对路由字符串,包括大小写和斜杠。还有一种情况是改了代码但没重启,调试模式没开的话旧进程还在跑,改完记得重启一次。

5.2 模板报错,说找不到文件

现象是页面抛出TemplateNotFound。原因是 Flask 默认只在项目根目录下的templates文件夹里找模板,文件夹名字拼错、层级放错、或者文件扩展名不对都会触发。解决方法是确认目录结构是项目根/templates/index.html,注意templates是复数,且和app.py在同一级。我第一次学的时候就把模板扔在了和 app.py 同级的目录里,找了半天原因,后来才明白这个约定。

5.3 数据提交了但页面数字不变

现象是点了提交,跳回首页,但计数还是老样子。原因多半是commit()漏写了,数据只在连接里没落盘;或者查询时连的是另一个数据库文件,路径不一致。解决办法是检查插入和查询两处connect的路径是否完全相同,以及插入后有没有commit()。可以在插入后临时打印一下影响行数,确认真的写进去了。

5.4 端口被占用,启动就报错

现象是运行python app.py后提示地址已被使用。原因是 5000 端口被别的程序占了,或者你之前启动的进程没关掉。解决办法是换一个端口,把启动那行改成app.run(debug=True, port=5001),或者找到占用端口的进程结束掉。这个坑很常见,换个端口是最省事的做法,不用纠结是谁占的。

5.5 中文显示成乱码

现象是页面上的中文变成了一串问号或方块。原因是 HTML 里没声明字符编码。解决办法是在模板的<head>里加上<meta charset="utf-8">,这一行基本能解决绝大多数乱码问题。数据库里存中文一般没问题,sqlite3 默认就是 UTF-8,问题多半出在页面渲染这一层。

6. 跑通之后往哪走:给新手的下一步路线

第一个例子跑通、表单能提交、数据能存能读,这栋试验楼的地基就算打好了。接下来别急着去啃大框架的文档,按下面这条路线走,每一步都建立在已经跑通的代码上,心里不慌。

先给现有 Demo 加一个“留言列表”页面。把SELECT COUNT(*)换成SELECT * FROM messages,用fetchall()拿到所有行,传给模板,在 HTML 里用{% for m in messages %}循环渲染出来。这一步能让你彻底理解“查询结果怎么变成页面内容”,是模板语法最实用的练习。做完之后,试着加一个删除功能,点一下删掉某条留言,路由用/delete/<int:id>这种带参数的形式,顺便理解一下 URL 参数是怎么传到函数里的。

再往后,把数据库操作从路由函数里抽出来,单独放一个文件,比如db.py,里面封装get_conn、query、execute几个小函数。这一步不是为了炫技,而是让你体会“代码分层的必要性”——当路由函数里塞满 SQL 的时候,改一处逻辑要翻半天。抽出来之后,路由只负责收请求、调函数、返响应,清爽很多。这个习惯越早养成越好。

然后可以接触一下用户登录的最小实现:加一张用户表,做一个登录页,用 session 记住登录状态。Flask 的 session 用起来很简单,但背后涉及的安全常识值得了解,比如密码不能明文存、要用哈希。这一步会让你对“状态”这个概念有实感——HTTP 本身是无状态的,是 session 让服务器记住了你是谁。

最后,等你把上面这些都跑过一遍,再去读 Flask 官方文档或者看更完整的项目,会发现那些曾经看不懂的章节突然有了意义。我自己的血泪经验是:每次加新功能之前,先把当前能跑的版本复制一份备份,改坏了直接退回去,不至于从头再来。这个习惯让我少熬了很多夜。从那以后我每次动手改代码前都强制走一遍备份,哪怕只改一行。希望这份试验楼能帮你迈出第一步,后面的楼,你自己就能一层层往上盖了。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进