1. 从零建站这件事,为什么我选了 WorkBuddy 加 Flask 这套组合
去年年底我接手了一个很小的需求:帮一个做农产品批发的朋友搭一个能每天更新价格行情的小站点。要求听起来不复杂——能发布每日价格、能按品类和日期查、手机上看不崩、后台自己能改数据,预算几乎为零。但真动手的时候,选型这一步就卡了我两天。
摆在面前的路其实就三条。第一条是 Shopify 这类托管电商,开箱即用,但它是为卖货设计的,我要的是“信息发布+查询”,硬套会别扭,而且每月固定成本对一个小站点来说不划算。第二条是 WordPress,生态成熟、插件多,但它的强项是内容管理,一旦我要做自定义的价格查询逻辑和数据结构,就得跟主题和插件打架,改起来束手束脚。第三条就是源码自建,用 Flask 加 SQLite 自己写。我最后选了第三条,原因很直接:这个站点的核心是“结构化的价格数据+轻量查询”,不是复杂的内容运营,自己写反而最省心,而且 Flask 足够轻,SQLite 一个文件就是整个数据库,部署和备份都简单到离谱。
这里就引出了 WorkBuddy 的角色。很多人第一次听到 WorkBuddy 会把它和 CodeBuddy 搞混,我一开始也分不清。简单说,CodeBuddy 更偏向纯代码补全和函数级生成,而 WorkBuddy 的定位是“工作台”式的协作助手,它能理解项目上下文、帮你规划任务、生成整段模块代码、还能按你自定义的指令去执行重复性工作。对我这种“一个人当三个人用”的独立开发者来说,WorkBuddy 最大的价值不是帮我写某一行代码,而是帮我把“建站”这件大事拆成可执行的小任务,并且在日更这种高频重复场景里替我扛掉大量机械劳动。这也是我写这篇实操记录的初衷——网上关于 WorkBuddy 使用教程、WorkBuddy 从入门到精通 这类内容不少,但真正把它放进一个完整建站项目里、并且坚持日更跑通的记录并不多,我想把踩过的坑和跑通的路径完整摊开。
这篇文章适合谁看?如果你是完全没碰过 Flask 和 SQLite 的新手,我会把 Python 安装、环境配置、数据库建表这些基础环节讲清楚,你照着做能跑起来;如果你已经会 Flask,但卡在“怎么把日常更新自动化”“怎么让 WorkBuddy 真正帮上忙”这些地方,那第二、三部分的实操细节和自定义指令会更对你有用。整套方案的核心技术栈就是 Python + Flask + SQLite,配合 WorkBuddy 做任务编排和代码生成,最终实现一个能日更、能查询、能自己维护的轻量站点。
2. 整体设计与思路拆解:为什么是这套架构
2.1 需求倒推架构,而不是先选技术再找场景
我见过太多人建站的第一步是“我要用某某框架”,结果做到一半发现框架的特性和需求对不上。我的习惯是先把需求翻译成数据流,再决定用什么。这个农产品价格站点的需求拆开其实就四件事:第一,每天录入一批价格数据,字段包括品类、规格、单价、日期、备注;第二,前台能按品类筛选、按日期排序展示;第三,支持简单的关键词搜索;第四,后台能增删改,且不需要复杂的权限体系。
把这四件事翻译成技术语言:需要一个关系型数据库存结构化数据,需要一个轻量 Web 框架提供路由和模板渲染,需要一个能定时或半自动触发数据录入的机制。SQLite 天然适合这种“单机、低并发、数据量不大”的场景,它不需要单独起服务,一个.db文件拷走就是完整备份。Flask 的路由和 Jinja2 模板机制,写查询页和详情页非常顺手,代码量小,调试直观。至于数据录入,我没上复杂的后台管理系统,而是用 Flask 写了一个受简单口令保护的管理页,配合 WorkBuddy 生成批量导入脚本,日更时基本是“整理好表格→跑脚本→刷新页面”三步。
提示:不要因为 SQLite “看起来简单”就低估它。对于日更、单表几千到几万行的场景,它的读写性能完全够用,真正需要警惕的是并发写入——后面排查部分我会专门讲这个坑。
2.2 WorkBuddy 在这套架构里到底承担什么
把 WorkBuddy 当成“更聪明的代码补全”是浪费它。我在这个项目里给它的定位是三层:任务规划层、代码生成层、重复劳动替代层。任务规划层指的是,建站初期我把“搭一个价格查询站”这个模糊目标丢给它,让它帮我拆成“环境准备→数据库设计→路由设计→模板设计→数据导入→部署”这样的阶段清单,我再按清单推进,避免漏项。代码生成层指的是,像 SQLite 建表语句、Flask 的路由函数、Jinja2 模板里的循环渲染这些有固定套路的代码,我描述清楚字段和逻辑后让它生成初稿,我再改。重复劳动替代层是最关键的——日更意味着每天都要做相似的数据清洗和导入,我通过 WorkBuddy 的自定义指令,把这套流程固化成一个可复用的操作,每天只需要替换源数据文件。
这里要澄清一个常见误解:WorkBuddy 和 CodeBuddy 不是二选一的关系。我在实际使用中,写具体函数逻辑时会借助 CodeBuddy 的补全,而项目级的规划、跨文件的改动、自定义工作流则交给 WorkBuddy。两者配合,效率比单用任何一个都高。至于网上流传的 WorkBuddy 从入门到精通 PDF 下载 这类资源,我的建议是别急着找“大全”,先把官方文档里关于自定义指令和工作台的部分读透,比看十份二手教程都管用。
2.3 为什么不上重型方案:一次真实的取舍
中途我动摇过一次,想换成 Django,理由是它自带 admin 后台,省得自己写管理页。但算了一笔账:Django 的 admin 确实省事,可它带来的是一整套约定和依赖,学习成本、部署体积、调试复杂度都上去了,而我需要的只是一个能改数据的页面。最后我用 Flask 加一个不到八十行的管理路由就解决了,还完全可控。这个取舍的逻辑值得说清楚:当你的需求是“一个点”,不要为了这个点引入“一个面”。SQLite 对 Django 来说也偏轻,属于杀鸡用牛刀。同理,前端我也没上 React 或 Vue,直接用 Jinja2 服务端渲染加一点原生 JS 做筛选,首屏快、SEO 友好、维护简单。
3. 核心细节解析与实操要点
3.1 环境准备:Python 安装与环境隔离的正确姿势
第一步是 Python 安装。Windows 用户去官网下安装包时,务必勾选“Add Python to PATH”,这一步漏了后面在命令行敲python会提示找不到命令,是新手最高频的坑。装完后在终端验证:
python --version pip --version能正常输出版本号就说明 PATH 配好了。macOS 和 Linux 用户一般自带 Python3,但建议用python3和pip3明确区分,避免和系统自带的 Python2 混淆。WorkBuddy 在 Linux 和 Ubuntu 环境下同样可用,如果你是在服务器上开发,装完 Python 后建议顺手装python3-venv。
接下来是环境隔离,这一步很多人跳过,结果项目依赖和系统环境互相污染,后面出问题极难排查。我的做法是每个项目一个虚拟环境:
python -m venv venv # Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate激活后命令行前面会出现(venv)标识。然后在虚拟环境里装依赖:
pip install flask如果你用 VSCode 开发,记得在 VSCode Python 环境配置里把解释器指向这个虚拟环境,否则编辑器提示的库和实际运行用的库会对不上,这个坑我踩过,表现为“代码里明明能跳转定义,运行却报 ModuleNotFoundError”。
3.2 数据库设计:SQLite 建表与字段类型选择
SQLite 的建表语句不复杂,但字段类型的选择直接影响后面查询和展示的顺畅度。我的价格表设计如下:
CREATE TABLE price ( id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT NOT NULL, spec TEXT, price REAL NOT NULL, unit TEXT DEFAULT '元/斤', record_date TEXT NOT NULL, note TEXT, created_at TEXT DEFAULT (datetime('now', 'localtime')) );几个细节值得展开。record_date我用 TEXT 存YYYY-MM-DD格式而不是用日期类型,原因是 SQLite 的日期处理相对弱,用文本存反而在排序和范围查询时更直观,WHERE record_date BETWEEN '2024-01-01' AND '2024-01-31'这种写法可读性极高。price用 REAL,虽然浮点数有精度问题,但价格展示到分位足够,真要严格可以用整数存“分”。created_at用默认值自动填,省得每次插入都手动传。
建好表后,我强烈建议装一个可视化工具。DB Browser for SQLite 是免费的,打开.db文件就能像 Excel 一样看数据、改数据、跑 SQL,对调试帮助巨大。Android Studio 里也有 SQLite 的可视化工具,但那是给移动开发用的,Web 项目用 DB Browser 更顺手。如果你习惯用 C# 生态,也可以用 C# 打开 SQLite 数据库的工具,但没必要为了看数据专门换语言。
注意:SQLite 数据库文件默认是不加密的,任何人拿到
.db文件就能读全部数据。如果你的价格数据涉及商业机密,要么在应用层做字段加密,要么把数据库文件放在 Web 根目录之外并严格控制服务器文件权限。SQLite 本身支持加密扩展,但配置较麻烦,小项目更推荐用文件权限来兜底。
3.3 Flask 路由设计:把查询逻辑写清楚
Flask 的核心是路由。这个站点我设计了三个主要路由:首页列表、按品类筛选、搜索。首页路由大致长这样:
from flask import Flask, render_template, request import sqlite3 app = Flask(__name__) def get_db(): conn = sqlite3.connect('price.db') conn.row_factory = sqlite3.Row return conn @app.route('/') def index(): category = request.args.get('category', '') keyword = request.args.get('q', '') conn = get_db() sql = "SELECT * FROM price WHERE 1=1" params = [] if category: sql += " AND category = ?" params.append(category) if keyword: sql += " AND (category LIKE ? OR note LIKE ?)" params.extend([f'%{keyword}%', f'%{keyword}%']) sql += " ORDER BY record_date DESC, id DESC LIMIT 100" rows = conn.execute(sql, params).fetchall() conn.close() return render_template('index.html', rows=rows)这里有个新手常问的问题:Flask 怎么查看从客户端获取的变量数据类型?答案是request.args拿到的永远是字符串,request.form也是字符串,需要数字就自己int()转换,别指望框架帮你转。另外conn.row_factory = sqlite3.Row这行很关键,它让查询结果可以像字典一样用列名访问,模板里写row['category']而不是row[1],可读性天差地别。
参数化查询用?占位符,这是防 SQL 注入的基本功,千万别用字符串拼接把用户输入直接塞进 SQL。我见过有人图省事写f"WHERE category = '{category}'",一旦有人构造恶意输入,整个库都危险。
3.4 模板渲染:Jinja2 里那些容易忽略的细节
模板部分我用的是 Jinja2,循环渲染数据行:
{% for row in rows %} <tr> <td>{{ row['category'] }}</td> <td>{{ row['spec'] or '-' }}</td> <td>{{ '%.2f'|format(row['price']) }}</td> <td>{{ row['record_date'] }}</td> </tr> {% endfor %}{{ row['spec'] or '-' }}这个写法处理空值很实用,比写 if 判断简洁。价格用'%.2f'|format()保留两位小数,避免出现3.1000000001这种浮点误差展示。Jinja2 默认会转义 HTML,所以用户输入的备注里如果有特殊字符不会被当成标签执行,这是安全默认值,别去关它。
4. 实操过程与核心环节实现
4.1 从零到能跑:完整搭建流程
我把整个搭建过程按时间顺序复盘一遍,你可以直接照着走。第一步,建项目目录,结构如下:
price_site/ ├── app.py ├── price.db ├── templates/ │ ├── index.html │ └── admin.html └── static/ └── style.css第二步,写app.py,把数据库连接、路由、启动代码放进去。第三步,用 DB Browser 手动建表,或者写一个init_db.py脚本跑一次建表语句。第四步,写模板。第五步,本地跑起来:
flask --app app run --debug--debug模式会在代码改动后自动重启,开发期非常方便,但上线一定要关掉,否则有安全风险。浏览器打开http://127.0.0.1:5000能看到页面就说明通了。
4.2 日更数据导入:WorkBuddy 自定义指令的实战用法
日更是这个项目的核心场景,也是最值得用 WorkBuddy 提效的地方。我每天的工作流是这样的:朋友把当天的价格发我一个 Excel 或 CSV,我需要清洗成统一格式再导入数据库。手动做的话,每天要花十几分钟,一个月下来就是好几个小时。我用 WorkBuddy 的自定义指令把这套流程固化了下来。
具体做法是,我先写一个通用的导入脚本import_data.py,它读取一个标准格式的 CSV,逐行插入数据库,并做去重(同品类同规格同日期已存在则更新而非新增):
import csv import sqlite3 def import_csv(path): conn = sqlite3.connect('price.db') with open(path, newline='', encoding='utf-8') as f: reader = csv.DictReader(f) for row in reader: existing = conn.execute( "SELECT id FROM price WHERE category=? AND spec=? AND record_date=?", (row['category'], row['spec'], row['record_date']) ).fetchone() if existing: conn.execute( "UPDATE price SET price=?, note=? WHERE id=?", (row['price'], row.get('note', ''), existing['id']) ) else: conn.execute( "INSERT INTO price (category, spec, price, record_date, note) VALUES (?,?,?,?,?)", (row['category'], row['spec'], row['price'], row['record_date'], row.get('note', '')) ) conn.commit() conn.close()这里的UPDATE语句就是 SQLite update 语句的典型用法,配合前面的存在性检查,实现了“有则更新、无则插入”的 upsert 效果。然后我把“读取指定 CSV 并导入”这件事配置成 WorkBuddy 的一个自定义指令,每天只需要把新文件放到指定目录,触发指令即可。WorkBuddy 的自定义指令推荐配置思路是:把“输入是什么、要做什么、输出到哪”描述清楚,越具体越稳定。
提示:CSV 的编码是个高频坑。Excel 导出的 CSV 在中文 Windows 上常是 GBK 编码,直接按 utf-8 读会报错或乱码。稳妥做法是导入前统一转成 UTF-8,或者在脚本里做编码探测。我现在的习惯是让朋友直接发 UTF-8 的 CSV,省去转换。
4.3 部署上线:让站点真正能被访问
本地跑通只是第一步,要让人访问得部署。小项目我推荐两种方式:一是用轻量的云服务器,装好 Python 环境,用 Gunicorn 加 Nginx 反向代理跑 Flask;二是用支持 Python 的托管平台,省去运维。Gunicorn 启动命令大致是:
gunicorn -w 2 -b 127.0.0.1:8000 app:app-w 2表示两个工作进程,对低并发足够。Nginx 负责把外部请求转发到 8000 端口,同时处理静态文件。这里有个 SQLite 的并发注意点:多个 Gunicorn 工作进程同时写数据库可能触发database is locked,解决办法是控制写入频率、给连接设置超时,或者干脆把写操作集中到单进程处理。我的站点读多写少,日更时基本没人访问,所以这个问题不突出,但你要心里有数。
5. 常见问题与排查技巧实录
5.1 高频问题速查表
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 命令行提示 python 不是内部命令 | 安装时没勾 PATH | 重装并勾选 Add to PATH,或手动配环境变量 |
| ModuleNotFoundError: flask | 虚拟环境没激活或装错环境 | 确认命令行有 (venv) 标识,重新 pip install |
| 数据库查询报 no such table | 建表脚本没跑或连错库文件 | 用 DB Browser 打开确认表存在,检查连接路径 |
| 中文显示乱码 | 编码不一致 | 统一用 UTF-8,CSV 导入前转码 |
| database is locked | 并发写入冲突 | 减少写并发,设置连接 timeout |
| 页面样式不生效 | 静态文件路径错 | 检查 static 目录和 url_for 写法 |
5.2 几个只有踩过才知道的坑
第一个坑是日期排序。我一开始用ORDER BY record_date DESC,结果发现同一天的数据顺序乱跳,因为同日期内没有稳定排序。加上id DESC作为第二排序键后就稳定了。第二个坑是浮点展示,前面提过,一定要格式化。第三个坑是 WorkBuddy 生成代码后的“想当然”——它生成的代码逻辑通常对,但字段名、表名可能和你实际的不一致,生成后必须逐行核对,尤其是 SQL 里的列名。我吃过一次亏,生成的 UPDATE 语句列名拼错,跑的时候没报错但数据没更新,排查了半天。
第四个坑是关于数据备份。SQLite 虽然一个文件就是全部,但正因为简单,很多人忘了备份。我的做法是每天导入完成后自动复制一份带日期的.db文件到备份目录,保留最近三十天。这个动作也交给 WorkBuddy 的定时任务去做,几乎零成本,但关键时刻能救命。
5.3 关于 WorkBuddy 使用的几点个人体会
用了一段时间后,我最大的感受是:WorkBuddy 的价值取决于你给它的上下文质量。你描述得越具体,它产出越可用。比如“帮我写个导入脚本”和“帮我写个读取 UTF-8 CSV、按 category+spec+record_date 去重、存在则更新 price 字段的 SQLite 导入脚本”,得到的结果完全不是一个层次。另外,WorkBuddy 工作台适合管理多步骤任务,把建站拆成阶段后,每天推进一点,进度一目了然。至于 WorkBuddy 国际版和国内版的差异,主要在使用环境和部分集成上,核心的工作台和自定义指令能力是一致的,按自己所在环境选就行。
最后分享一个小技巧:把常用的自定义指令整理成一个清单文档,标注每个指令的输入输出和适用场景。日更这种重复场景,指令库越完善,你每天花的时间越少。我现在整套日更流程从收到数据到页面更新,稳定在五分钟以内,这在没有 WorkBuddy 之前是不敢想的。