【免费下载链接】pelican
Static site generator that supports Markdown and reST syntax. Powered by Python.
本篇技术指南以 Pelican 测试套件中的 draft_page_markdown.md 为切入点,讲解如何用 Markdown 为 Pelican 静态站点生成"草稿(draft)"状态的页面。你将掌握status元数据的取值语义、草稿页面的生成与输出原理、DRAFT_*系列 URL 配置,以及如何借助DEFAULT_METADATA自动防止文章被意外发布,从而搭建一套"先草稿后发布"的内容管理流程。
从一个 12 行的测试文件说起
在 Pelican 仓库的测试目录pelican/tests/TestPages/下,存放着一组用于验证PagesGenerator行为的页面样本,其中 draft_page_markdown.md 完整内容如下:
title: This is a markdown test draft page status: draft Test Markdown File Header ========================= Used for pelican test --------------------- The quick brown fox . This page is a draft这个文件麻雀虽小,五脏俱全,恰好演示了 Pelican 草稿页面的全部关键要素:
- Markdown 前置元数据(front matter):文件开头用
key: value形式声明元数据,title指定页面标题,status: draft声明该页面处于草稿状态; - 正文使用标准 Markdown 语法:
=====下划线构成一级标题(Setext 风格),-----构成二级标题,正文为普通段落文本; - 测试样本定位:它是与 draft_page.rst(reST 版本)并列的 Markdown 版本,用于证明无论内容格式是 Markdown 还是 reST,
status: draft都能被一致地识别与处理。
仓库中还提供了这一机制的 reST 对照样本 draft_page.rst,其写法是在文档末尾附加:status: draft字段,正文结构完全一致。两份样本共同构成了"同一声明、双格式验证"的测试设计。
status 元数据:页面与文章的四种状态
status不是自由文本,它在源码层面对取值做了严格约束。在 pelican/contents.py 中,Page类(页面)与Article类(文章)均定义了相同的状态白名单:
class Page(Content): mandatory_properties = ("title",) allowed_statuses = ("published", "hidden", "draft", "skip") default_status = "published" default_template = "page"| 状态值 | 行为语义 | 典型用途 |
|---|---|---|
published | 默认状态;正常参与首页、分类、标签等索引与聚合 | 正式对外发布的内容 |
draft | 输出到独立的 drafts 目录,不进入任何索引页与订阅源 | 待审核、待完善的内容 |
hidden | 按*_SAVE_AS正常输出,但默认不进入标签、分类、作者索引与主订阅源 | 创建"未列出的私密页" |
skip | 完全忽略,不处理也不输出 | 临时禁用某篇内容 |
从源码结构可以推断,状态判定发生在生成阶段而非解析阶段:Page/Article解析后,由生成器读取page.status属性完成分发(详见下一节),因此只需修改元数据中的status值,即可在不改动正文的前提下切换页面的发布状态。
草稿页面的模板与类名细节
Page._expand_settings()中存在一个容易被忽略的细节(pelican/contents.py):
def _expand_settings(self, key: str) -> str: klass = "draft_page" if self.status == "draft" else None return super()._expand_settings(key, klass)即草稿页面在展开输出路径时使用draft_page这一类别标识,而草稿文章在 Article._expand_settings 中对应使用draft类别。这意味着在配置PAGE_SAVE_AS等模板字符串时,可以像下面这样为草稿页面单独定制输出路径:
PAGE_SAVE_AS = "pages/{slug}.html" # 草稿页面可被路由到独立目录,例如: DRAFT_PAGE_SAVE_AS = "drafts/{slug}.html"生成器如何"分流"草稿页面
页面状态的分类逻辑位于PagesGenerator.generate_context()(pelican/generators.py)。生成器遍历PAGE_PATHS下的每一个文件,读取为Page对象后按状态分发:
if page.status == "published": all_pages.append(page) elif page.status == "hidden": hidden_pages.append(page) elif page.status == "draft": draft_pages.append(page) elif page.status == "skip": raise AssertionError("Documents with 'skip' status should be skipped")随后,三个列表各自经过翻译处理(process_translations)与排序(order_content)后,分别挂载为generator.pages、generator.hidden_pages、generator.draft_pages,并统一写入模板上下文generator.context。文章侧的分流逻辑完全对称,见 pelican/generators.py:published进all_articles、draft进all_drafts、hidden进hidden_articles。
值得注意的是,generate_output()(pelican/generators.py)会对草稿页面执行完整的写文件流程(调用writer.write_file并传入draft.save_as),也就是说草稿页面虽然不进索引,但依然会被渲染成静态 HTML 文件——这正是"给朋友预览"场景的实现基础:草稿有独立 URL,只是不对外暴露入口。
文章侧的特殊规则:未来日期自动转草稿
对于文章(Article),草稿状态还有一个自动触发途径(pelican/contents.py):当设置WITH_FUTURE_DATES = False(默认值)时,若文章date晚于当前时间,其status会被自动改写为draft,实现"定时发布"效果;反过来,若一篇草稿文章没有声明date,Pelican 会将其日期补为datetime.datetime.max,确保它在按时间排序时被排到最后。页面对此不做处理,因为页面不强制要求日期字段(Page.mandatory_properties = ("title",))。
草稿的 URL 与输出位置
草稿的输出路径由 pelican/settings.py 中的默认设置决定:
| 设置项 | 默认值 | 说明 |
|---|---|---|
DRAFT_URL | drafts/{slug}.html | 草稿文章的 URL |
DRAFT_SAVE_AS | drafts/{slug}.html | 草稿文章的输出路径 |
DRAFT_LANG_URL | drafts/{slug}-{lang}.html | 多语言草稿文章的 URL |
DRAFT_LANG_SAVE_AS | drafts/{slug}-{lang}.html | 多语言草稿文章的输出路径 |
可以看到,草稿文章默认统一落入站点根目录的drafts/文件夹(例如drafts/my-post.html),与正式内容的ARTICLE_URL/ARTICLE_SAVE_AS路径天然隔离。这一设计同样适用于草稿页面:draft_page_markdown.md在测试中被渲染为草稿页面后,其输出目录与正式页面(如pages/下)互不干扰。你可以覆盖上述四个设置,将草稿集中放置到任意自定义目录。
另外,草稿内容不会被加入任何索引页或订阅源。ArticlesGenerator在构建标签、分类、作者页及 feed 时只遍历正式文章列表,草稿列表被排除在外(参见 pelican/generators.py 附近对"drafts"上下文的写入位置)。从 changelog 看,草稿功能经历了"支持草稿文章 → 页面支持 draft 状态 → 支持语言翻译草稿"的演进(docs/changelog.rst),这也解释了DRAFT_LANG_*的存在。
把"所有内容默认草稿"写进配置
官方文档 Publishing drafts 提供了一个非常实用的模式:如果担心文章还没写完就被意外发布,可以在pelicanconf.py中通过DEFAULT_METADATA把默认状态设为草稿:
DEFAULT_METADATA = { 'status': 'draft', }这样所有未显式声明status的文章/页面都会自动成为草稿;当内容真正完成时,只需在文件元数据中显式覆盖:
title: 我的新文章 status: published同理,若要手动把某篇内容转为草稿,将其元数据改为status: draft即可。这一机制与 draft_page_markdown.md 的做法完全一致——草稿状态就是元数据里的一个字段,Pelican 据此决定内容的去处。
测试如何验证草稿页面行为
草稿页面的行为在测试套件中有多处验证,可作为理解机制的参照:
- pelican/tests/test_generators.py 的
TestPageGenerator.test_generate_context():将PAGE_PATHS指向TestPages目录后,断言generator.draft_pages恰好包含三条记录,其中就包括["This is a markdown test draft page", "draft", "page"]——元组依次为标题、状态、模板,可见草稿页面的template仍为默认的page; - 同一测试还同时断言
generator.pages、generator.hidden_pages与generator.context["draft_pages"],证明草稿页面与正式、隐藏页面在上下文与生成器属性两个层面都被正确分流; - pelican/tests/test_cache.py 验证缓存机制下
generator.draft_pages在两次读取(首次构建与缓存命中)间保持一致,说明草稿列表同样参与缓存化处理; - pelican/tests/test_contents.py 则从
Content对象层面验证status: draft元数据能被正确解析并写入static.status。
此外,命令行在每次构建结束后会输出处理统计,其中会区分N articles、M drafts、K draft pages等(见 pelican/init.py),方便你直观确认草稿数量是否符合预期。
与 hidden、skip 的边界
理解草稿的最佳方式之一是把它和另外两个"非发布"状态放在一起对比:
- draft:渲染为独立 HTML(
drafts/目录),不进任何索引与 feed,适合"发布前预览"; - hidden:按正式路径输出(
ARTICLE_SAVE_AS),但默认不进标签/分类/作者索引和主 feed,效果是"有 URL 但不出现在列表里",适合不公开的私密内容; - skip:完全跳过解析与输出,既不生成文件也不进索引(docs/content.rst)。
三者的共同点是都不会出现在首页、分类页、标签页等公开聚合位置;区别在于草稿有独立输出目录、隐藏内容按正式路径输出、跳过内容不输出。
小结:一套可落地的草稿工作流
结合官方文档、测试样本与源码实现,在 Pelican 中管理草稿页面的完整工作流如下:
- 在
pelicanconf.py中设置DEFAULT_METADATA = {'status': 'draft'},从源头避免误发布; - 编写内容时使用 Markdown(或 reST)前置元数据,如 draft_page_markdown.md 所示声明
title与status; - 运行
pelican content构建站点,草稿自动渲染到drafts/{slug}.html,可通过该 URL 分享给协作者预览; - 内容定稿后,将元数据改为
status: published重新构建,文章/页面即进入正式索引与订阅源; - 若某篇内容希望"有链接但不公开",改用
status: hidden;若想彻底停用某篇内容,使用status: skip。
这套机制全部由status一个字段驱动,配合生成器分流(pelican/generators.py)与DRAFT_*URL 配置(pelican/settings.py),即可在纯静态站点上实现"草稿 → 预览 → 发布"的轻量级内容治理。
【免费下载链接】pelican
Static site generator that supports Markdown and reST syntax. Powered by Python.
相关推荐
Pelican 页面草稿与自定义模板:基于 reST 元数据的 status / template 机制实战
Pelican 页面草稿与自定义模板:基于 reST 元数据的 status / template 机制实战 本文以 Pelican 官方测试用例 draft_
Pelican 草稿(Draft)机制全解析:从 `draft_page.rst` 看 status 元数据与草稿生成管线
Pelican 草稿(Draft)机制全解析:从 draft_page.rst 看 status 元数据与草稿生成管线 本指南以 Pelican 测试套件中的
从排序测试页看 Pelican 页面排序机制:PAGE_ORDER_BY 配置与 reST 元数据实战
从排序测试页看 Pelican 页面排序机制:PAGE_ORDER_BY 配置与 reST 元数据实战 Pelican 是一个基于 Python 的静态站点生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考