1. 为什么我选择 WorkBuddy + Flask + SQLite 这套组合
1.1 从零建站的真实需求拆解
很多人一提到建站,第一反应就是 WordPress,或者干脆上 Shopify 这类托管方案。我一开始也是这么想的,但实际跑了一遍之后发现,如果你只是想做一个自己能完全掌控、数据在自己手里、后续想怎么改就怎么改的小型内容站,WordPress 那套东西反而会变成负担。插件更新、主题兼容、数据库迁移,每一样都是时间成本。
我这次的需求很明确:一个可以日更的站点,内容以文字为主,需要有一个后台能让我快速发布,前台访问速度要快,数据要能随时导出备份,整个项目最好能在一台最低配的服务器上跑起来。基于这几个硬性条件,我把技术选型锁定在了Flask + SQLite这套轻量组合上,而 WorkBuddy 则负责把建站过程中那些重复性的、需要查文档才能搞定的环节给自动化掉。
先说 Flask。它是一个 Python 的微框架,所谓“微”并不是说功能少,而是说它不替你做决定。数据库用什么、模板引擎用什么、表单怎么处理,全都由你自己选。这对于建站来说其实是好事,因为你可以按需拼装,不会被迫接受一堆用不上的东西。我试过用 Django 做同样的事情,光是理解它的 ORM 和 admin 后台就花了大半天,而 Flask 我半小时就能跑起来一个能用的页面。
再说 SQLite。它是一个文件型数据库,整个数据库就是一个.db文件,不需要单独安装数据库服务,不需要配置用户名密码,不需要开端口。对于日更型的小站来说,读多写少,并发压力几乎为零,SQLite 完全够用。而且备份极其简单,直接把那个.db文件复制走就行。我之前用过 MySQL,光是安装和配置就折腾了一个小时,而 SQLite 是 Python 内置支持的,import sqlite3就能用。
WorkBuddy 在这套组合里扮演的角色,是一个建站流程的加速器。它不是一个具体的框架,而是一个能理解你意图、帮你生成代码骨架、帮你排查报错的工具。比如我输入“帮我写一个 Flask 路由,接收 POST 请求,把标题和正文存到 SQLite”,它就能直接给出可运行的代码,省去了我翻文档的时间。热词里提到的workbuddy skill和workbuddy自定义指令推荐,其实就是指你可以把常用的建站操作固化下来,下次直接调用。
1.2 三种建站方式的真实对比
在动手之前,我把 Shopify、WordPress 和自建站这三种方式做了一个横向对比,这张表是我自己实际用过之后总结的,不是网上抄的:
| 对比维度 | Shopify | WordPress | 自建站(Flask+SQLite) |
|---|---|---|---|
| 上手难度 | 极低,注册就能用 | 低,但插件配置复杂 | 中等,需要懂一点 Python |
| 数据掌控 | 数据在平台 | 数据在自己服务器 | 数据完全在自己手里 |
| 月成本 | 几百到几千 | 服务器+域名,约几十 | 服务器+域名,约几十 |
| 定制自由度 | 受平台限制 | 受主题和插件限制 | 完全自由 |
| 日更效率 | 后台发布,较快 | 后台发布,插件多了会卡 | 自己写发布页,最快 |
| 适合场景 | 电商卖货 | 博客、企业站 | 个人站、工具站、数据展示 |
我最终选自建站,核心原因是日更这个需求。Shopify 和 WordPress 的后台虽然能用,但每次发布都要经过一堆加载和跳转,而我自己的发布页只有一个表单,填完点提交就完事,整个过程不到三秒。热词里提到的shopify、wordpress、自建站什么区别,本质上就是控制权的区别:你愿意用便利性换控制权,还是用控制权换便利性。
1.3 WorkBuddy 在建站流程中的定位
WorkBuddy 不是替代 Flask 的东西,它更像是一个副驾驶。我实际用下来的感受是,它在以下几个环节特别有用:
- 生成代码骨架:比如我要写一个文章列表页,直接描述需求,它给出 Jinja2 模板和对应的路由函数。
- 排查报错:Flask 的报错有时候比较隐晦,把错误信息贴给 WorkBuddy,它能快速定位到是哪一行的问题。
- SQL 语句生成:SQLite 的
UPDATE语句我老是记不住字段顺序,直接让 WorkBuddy 生成,准确率很高。 - 部署命令整理:从本地到服务器,需要哪些命令,它能一次性列出来。
热词里出现的codebuddy和workbuddy,我理解是同一类工具的不同叫法,核心能力都是用自然语言驱动代码生成和问题排查。你不需要背命令,只需要把你想做的事情说清楚。
2. 环境搭建:从零到跑通第一个页面
2.1 Python 安装与虚拟环境配置
这一步是很多新手卡住的地方。我见过太多人因为 Python 版本混乱、包冲突而放弃建站。我的建议是:永远用虚拟环境,不要往系统 Python 里直接装包。
Windows 下的操作流程:
- 去 Python 官网下载最新稳定版,安装时务必勾选“Add Python to PATH”。
- 打开命令行,输入
python --version,确认版本号显示正常。 - 创建一个项目文件夹,比如
myblog,进入该文件夹。 - 执行
python -m venv venv,这会生成一个venv文件夹。 - 激活虚拟环境:Windows 下执行
venv\Scripts\activate,Mac 或 Linux 下执行source venv/bin/activate。 - 激活后命令行前面会出现
(venv)字样,说明成功。
Linux 下的操作略有不同,热词里提到的workbuddy linux和workbuddy ubuntu,说明不少人在 Linux 环境下操作。Ubuntu 下通常系统自带 Python3,但可能需要手动安装python3-venv:
sudo apt update sudo apt install python3-venv python3-pip python3 -m venv venv source venv/bin/activate注意:虚拟环境激活后,你安装的所有包都只在这个环境里生效,不会污染系统。这是避免版本冲突最有效的手段。
2.2 Flask 与 SQLite 的安装
虚拟环境激活后,安装 Flask 只需要一行:
pip install flaskSQLite 不需要安装,Python 标准库自带sqlite3模块。但如果你想要一个可视化工具来查看和编辑数据库,我推荐DB Browser for SQLite。热词里提到的db browser for sqlite和androidstudio sqlite的可视化工具,说的就是这类工具。DB Browser 的好处是免费、跨平台、界面直观,打开.db文件就能看到表结构和数据,还能直接执行 SQL。
安装完 Flask 后,可以执行pip freeze查看已安装的包,确认 Flask 及其依赖都在列表里。
2.3 项目目录结构设计
一个清晰的目录结构能让后续开发少走很多弯路。我实际使用的结构如下:
myblog/ ├── venv/ ├── app.py ├── database.db ├── templates/ │ ├── index.html │ ├── post.html │ └── admin.html ├── static/ │ ├── style.css │ └── script.js └── requirements.txtapp.py是主程序,包含所有路由和数据库操作。database.db是 SQLite 数据库文件,首次运行时会自动创建。templates存放 Jinja2 模板,Flask 默认从这里读取 HTML。static存放 CSS、JS、图片等静态资源。requirements.txt记录依赖,方便部署时一键安装。
这个结构不是唯一的,但它是经过验证的、适合小型站点的最简结构。我试过把路由拆成多个文件,结果对于日更站来说反而增加了维护成本,所以最终回归到单文件。
3. 数据库设计:SQLite 建表与核心操作
3.1 文章表的字段设计与理由
SQLite 建表用CREATE TABLE语句。我的文章表设计如下:
CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );每个字段都有明确理由:
id是自增主键,SQLite 中用INTEGER PRIMARY KEY AUTOINCREMENT实现。title和content是核心内容,设为NOT NULL防止空文章。created_at和updated_at用时间戳,方便按时间排序和显示更新日期。
提示:SQLite 没有专门的日期类型,
TIMESTAMP实际上是以文本形式存储的,但 SQLite 提供了日期函数可以正常处理。
3.2 增删改查的 SQL 语句实操
插入文章:
INSERT INTO posts (title, content) VALUES (?, ?);这里的?是参数占位符,千万不要用字符串拼接,否则会有 SQL 注入风险。Python 的sqlite3模块会自动处理转义。
查询文章列表:
SELECT id, title, created_at FROM posts ORDER BY created_at DESC;查询单篇文章:
SELECT * FROM posts WHERE id = ?;更新文章(热词里提到的sqlite update语句):
UPDATE posts SET title = ?, content = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?;删除文章:
DELETE FROM posts WHERE id = ?;这五条语句覆盖了日更站的全部数据操作。我实际写下来,整个数据库层不到 50 行代码。
3.3 用 DB Browser 可视化验证数据
写完数据库操作后,不要急着写前端。先用 DB Browser 打开database.db,执行几条 SQL,确认数据能正常写入和读取。这一步能帮你排除掉大部分数据库层面的问题。
DB Browser 的使用流程:
- 打开软件,点击“Open Database”,选择你的
.db文件。 - 切换到“Execute SQL”标签页,粘贴 SQL 语句,点击执行按钮。
- 切换到“Browse Data”标签页,选择
posts表,就能看到所有数据。
我踩过的一个坑是:Flask 运行时数据库文件被占用,DB Browser 无法写入。解决办法是先停止 Flask 服务,再用 DB Browser 操作,或者用只读模式打开。
4. Flask 路由与模板:让页面跑起来
4.1 核心路由函数编写
Flask 的路由用装饰器定义。首页路由如下:
from flask import Flask, render_template, request, redirect, url_for import sqlite3 app = Flask(__name__) DATABASE = 'database.db' def get_db(): conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row return conn @app.route('/') def index(): conn = get_db() posts = conn.execute('SELECT id, title, created_at FROM posts ORDER BY created_at DESC').fetchall() conn.close() return render_template('index.html', posts=posts)这里有几个关键点:
conn.row_factory = sqlite3.Row让查询结果可以像字典一样按字段名访问,而不是只能按索引。fetchall()返回所有结果,fetchone()返回一条。- 每次操作后都要
conn.close(),否则连接会泄漏。
热词里提到的flask查看从客户端获取的变量数据类型,在 Flask 中通过request.form.get('title')获取表单数据,默认是字符串类型。如果需要其他类型,要手动转换。
4.2 Jinja2 模板的变量渲染
index.html模板的核心逻辑:
<!DOCTYPE html> <html> <head> <title>我的日更站</title> </head> <body> <h1>文章列表</h1> {% for post in posts %} <div class="post"> <h2><a href="/post/{{ post['id'] }}">{{ post['title'] }}</a></h2> <p>{{ post['created_at'] }}</p> </div> {% endfor %} </body> </html>Jinja2 的语法很直观:{% %}包裹逻辑,{{ }}包裹变量。post['id']这种写法是因为用了sqlite3.Row,如果不用 Row,就得写post[0]。
4.3 发布页与表单处理
发布页需要一个表单,提交后写入数据库:
@app.route('/admin', methods=['GET', 'POST']) def admin(): if request.method == 'POST': title = request.form.get('title') content = request.form.get('content') if title and content: conn = get_db() conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)', (title, content)) conn.commit() conn.close() return redirect(url_for('index')) return render_template('admin.html')methods=['GET', 'POST']是关键,不写的话默认只接受 GET 请求,表单提交会报 405 错误。conn.commit()也是必须的,SQLite 默认不会自动提交。
5. 日更实操:从写稿到发布的完整流程
5.1 内容准备与格式规范
日更最难的不是技术,是持续产出。我给自己定了一个规矩:每天至少写 500 字,主题不限,但必须当天发布。内容准备阶段,我通常用 Markdown 写草稿,然后粘贴到发布页。
这里有一个小技巧:如果你的内容包含 HTML 标签,Flask 默认会转义,防止 XSS 攻击。如果你确实需要渲染 HTML,可以用|safe过滤器,但只对自己写的内容使用,不要对用户输入使用。
5.2 发布操作与数据确认
发布流程:
- 打开
/admin页面。 - 填写标题和正文。
- 点击提交,页面跳转到首页。
- 确认新文章出现在列表顶部。
- 用 DB Browser 打开数据库,确认数据已写入。
这五步我每天重复一次,整个过程不超过两分钟。热词里提到的workbuddy使用教程和workbuddy从入门到精通,其实核心就是把这些重复操作固化下来,形成肌肉记忆。
5.3 备份策略与自动化脚本
SQLite 的备份极其简单,写一个 Python 脚本,每天定时复制.db文件:
import shutil import datetime today = datetime.date.today().strftime('%Y%m%d') shutil.copy('database.db', f'backup/database_{today}.db')配合系统的定时任务(Linux 下用crontab,Windows 下用“任务计划程序”),就能实现自动备份。我实测下来,一个 10MB 的数据库文件,复制耗时不到 0.1 秒。
6. 常见问题与排查技巧实录
6.1 数据库锁定与并发问题
问题:Flask 运行时,DB Browser 无法写入数据库,提示“database is locked”。
原因:SQLite 默认使用文件锁,同一时间只允许一个写入操作。
解决:停止 Flask 服务后再用 DB Browser 操作,或者用只读模式打开。如果确实需要并发写入,可以启用 WAL 模式:
PRAGMA journal_mode=WAL;WAL 模式允许读写同时进行,但会生成额外的-wal和-shm文件。
6.2 模板找不到与静态文件 404
问题:访问页面时报TemplateNotFound或静态文件 404。
原因:Flask 默认从templates和static文件夹读取,文件夹名必须完全一致,且位置要在app.py同级目录。
解决:检查目录结构,确认templates/index.html存在。如果自定义了目录,要在Flask(__name__, template_folder='...')中指定。
6.3 端口占用与部署常见错误
问题:启动时报Address already in use。
原因:5000 端口被占用,可能是上次的 Flask 进程没关干净。
解决:Linux 下用lsof -i:5000找到进程号,然后kill -9 进程号。Windows 下用netstat -ano | findstr :5000找到 PID,然后在任务管理器中结束。
部署到服务器时,不要直接用app.run(),要用 Gunicorn 或 uWSGI。Gunicorn 的启动命令:
gunicorn -w 4 -b 0.0.0.0:8000 app:app-w 4表示 4 个 worker 进程,app:app表示app.py中的app对象。
6.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 405 Method Not Allowed | 路由没写 methods | 添加methods=['GET', 'POST'] |
| 数据写入后查不到 | 没执行 commit | 添加conn.commit() |
| 中文乱码 | 编码不一致 | 确保文件和数据库都用 UTF-8 |
| 页面样式丢失 | 静态文件路径错误 | 用url_for('static', filename='style.css') |
| 部署后 502 | Gunicorn 没启动 | 检查进程和端口 |
提示:遇到报错先看终端输出,Flask 的调试模式会给出详细堆栈。生产环境记得关闭 debug,否则有安全风险。
7. 我实际跑下来的一些体会
这套方案我从零开始搭,到第一篇文章发布,总共花了不到三个小时。其中大部分时间花在调试模板和数据库连接上,真正写代码的时间并不多。WorkBuddy 在这个过程中帮我省去了大量查文档的时间,尤其是 SQL 语句和 Flask 路由的写法,直接描述需求就能得到可用的代码。
日更这件事,技术门槛其实很低,难的是坚持。我的做法是把发布流程压缩到极致,打开页面、粘贴内容、点提交,三步完成。任何多余的步骤都会成为放弃的理由。
另外,SQLite 虽然简单,但不要用它做高并发的事情。如果你的站点突然流量暴涨,或者需要多用户同时写入,那就该考虑换 PostgreSQL 或 MySQL 了。工具没有好坏,只有合不合适。
最后分享一个小技巧:在app.py里加一行app.config['TEMPLATES_AUTO_RELOAD'] = True,这样修改模板后不用重启服务,刷新页面就能看到效果,调试效率会高很多。