返回 · 2026-05-10T15:49:00+00:00
py-blog:一个单文件博客
最近在搭建博客时实在是忍无可忍,最后决定自己搞一个够用就可以的博客,又想到也许可能有人会有和我一样的需求,于是写一篇文章来进行简要说明
摘要
- 它是什么:
blog.py里装着完整站点——FastAPI + SQLite + Jinja2,没有 Node、没有单独构建步骤。 - 它想成为的样子:一块够用就好、边界清晰的小地方:你能读完代码,也能先写完文章再考虑扩展。
- 它不假装的样子:不是富文本工作台,不是评论托管商,也不是主题商店;图床、评论若需要,从外面接进来即可。
- 怎么用:装依赖、运行脚本;环境与表格详见文末及 README.md。
- 尺度感:更像个人站与学习样本;仓库里没有成套自动化测试与 lint,别把它当成「对标头部 CMS 的框架」来期待。
- 基础保障:迭代时会借助 Cursor 做一次简易功能测试,对核心路径做冒烟式确认;这与「尚未接入 CI / 单测」并存,属于轻量人工门禁而非完备质量体系。
有些人上手博客时,更在意的是:多久能发出第一篇。也有一类产品会把目录、插件、主题和流水线排在写字之前——那条路完全合理,只是不一定是你此刻需要的那条路。
py-blog 更接近另一种假设:你手头已经有 Markdown,想要一个能贴上域名、偶尔改两行样式的容器。它不必证明自己「体系完备」,只要在你打开仓库时,不会因为路径太深而不知从何看起。
它试着扮演的角色
这个项目更愿意被想象成:
- 一页能跑起来的站点:Markdown 上传后保存时预渲染成 HTML,访客打开页时不再重复解析一遍。
- 依赖很少的运行图景:SQLite、单管理员、密码登录外加常见的 Session / CSRF——足够应付「一个人维护」的场景。
- 放在反代后面也很好相处:默认监听本机端口,前面挂 Nginx、配 HTTPS 是常见用法;备案文案可以用环境变量塞进页脚。
技术面目很简单:单文件 Python,HTTP、存储和模板渲染都在同一个文件里讲完,没有前端打包链路。
单文件对它意味着什么
形态不是口号,而是它给自己的规矩:
- 「从哪里读起」只有一个答案:没有纵深很深的包结构;能读一点 Python,就能顺着路由和模板字符串往下看。
- 「从哪里改样式」也多半在同一个文件里:搜得到字符串,就改得到界面,不必在十几个目录间跳转。
- 部署时脑子里只装一件事:装依赖、执行
python blog.py,终端里会看到启动信息与(若未预设密码)一次性管理员口令——没有 Webpack,也没有 Node。
所以如果有人在群里问「主体代码在哪」,答案可以短到一个文件名。这对自用、自学或随手 fork,都算一种减负。
它不打算成为什么
边界写得清楚,反倒轻松:默认安装里不包含一整套周边产业。
- 没有内置富文本编辑器——正文假定你用习惯的编辑器写 Markdown。
- 没有内置评论——需要时再接 Giscus、Disqus、Waline 一类服务。
- 没有主题市场——观感不满意时,改模板字符串就是了;它接受自己「不那么开箱即炫」。
图片默认走外链 URL,而不是把存储、备份和迁移绑死在进程里。换句话说,它承认自己只是站点的一层壳,不把世上所有需求都吞进仓库。
怎么使用
克隆仓库并安装依赖后,直接运行:
git clone https://github.com/WHC2006/py-blog.git
cd py-blog
pip install -r requirements.txt
python blog.py
浏览器访问 http://127.0.0.1:8765,前台在 /,管理员登录在 /admin/login。
若未设置 BLOG_ADMIN_PASSWORD,首次启动会在终端打印一次随机管理员密码,请及时保存;也可通过环境变量显式设定密码与站点标题等。SQLite 与运行数据默认落在 data 目录(可通过环境变量调整)。
常用环境变量一览如下(完整说明仍以仓库内 README.md 为准):
| 变量 | 默认 | 说明 |
|---|---|---|
BLOG_HOST |
127.0.0.1 |
监听地址 |
BLOG_PORT |
8765 |
监听端口 |
BLOG_DATA_DIR |
data |
SQLite 与运行数据目录 |
BLOG_SITE_TITLE |
— | 站点标题 |
BLOG_ADMIN_PASSWORD |
— | 管理员密码;未设置则首次启动随机生成并打印 |
BLOG_SECRET_KEY |
— | Session 签名密钥;未设置则自动生成并持久化 |
BLOG_ICP_TEXT |
— | 页脚备案文案 |
BLOG_ICP_URL |
— | 备案查询链接 |
更多能力(KaTeX、目录树、排序方式等)见 README 的「功能一览」。
对你来说,它可能意味着什么
这里没有对错,只有匹配与否:
- 若你需要:个人站点、一份「愿意读完」的后端示例、在一个文件里看清 FastAPI / SQLite / Jinja2 怎样拼在一起——它大概率够用。
- 若你指望:多作者协作、复杂权限、插件生态、重度运营与 SEO 工具箱——那不是它的赛道;勉强对齐只会双方都累。
另外:仓库目前没有自动化测试套件,也没有配套 lint,谈不上工业级的回归矩阵。维护侧会用 Cursor 跑一轮简易功能测试:启动服务、点一遍后台与前台的关键链路,确认基础能力未被明显打断——相当于冒烟,而不是替代测试工程。
稳定性仍然离不开你自己环境与负载下的验证;高流量、严合规的生产形态,需要你再做架构与运维上的加固——这是实情,不是套话。
在腾讯云上部署(极简提示)
在腾讯云 CVM 或轻量应用服务器上,常见做法是本机运行 python blog.py,前面用 Nginx 反向代理到默认的 127.0.0.1:8765,并配置 HTTPS;备案展示可通过 BLOG_ICP_TEXT、BLOG_ICP_URL 注入页脚。完整 Nginx 示例与环境变量说明见 README.md。若域名前有 EdgeOne 或 WAF,宜为 /admin/* 放行,避免后台登录 POST 被拦。
MIT,源码:https://github.com/WHC2006/py-blog.git。
它更适合被看成一小块可自行改写的底座:合拍就用,不合拍就换——仅此而已。