Docs 升级指南:从 2.2.0 到 5.0.0 的版本演进与破坏性变更处理

原创2026-09-13 17:14:421,862 阅读
文章标签:前端后端内容协同知识管理

Docs 升级指南:从 2.2.0 到 5.0.0 的版本演进与破坏性变更处理

Docs 是一个基于 Django + React 构建的开源实时协作文档编辑器。本文基于仓库根目录的 UPGRADE.md,系统梳理该项目从 2.2.0 到 5.0.0 各版本升级时必须知晓的破坏性变更、配置迁移与新能力,并结合 后端视图层源码、设置文件 与 环境变量示例 做源码级印证。读完本文,你将掌握 Docs 各版本的升级路径、migrate 的正确用法、文档内容 API 的迁移方法、AI 配置项的重命名规则以及协作服务(yProvider)鉴权架构的变化,从而安全、顺序地完成自建实例的升级。

升级的总体原则

UPGRADE.md 在开篇就明确了三条升级纪律:

  1. 必须顺序升级:从一个版本升级到下一个版本时,不能跳过 minor/major 版本;只有 fix(补丁)版本可以跳过。例如从 4.0.0 升级到 5.0.0 之前,必须先经过 4.6.0。
  2. 格式规范:变更日志格式遵循 Keep a Changelog,版本号遵循 Semantic Versioning(MAJOR.MINOR.PATCH,MAJOR 变更代表破坏性变更)。
  3. 绝大多数升级只需跑一次数据迁移:在 Docker 容器内执行 Django 迁移命令:
python manage.py migrate

在开发环境中,可以直接使用 Make 封装的快捷目标:

make migrate

仓库根目录的 Makefile 提供了完整的开发辅助命令(make bootstrap、make run、make demo、make superuser 等),其中 bootstrap 会在拉取新代码后构建容器、安装依赖并运行数据库迁移。

5.0.0(2026-04-30):文档内容管理 API 的重大重构

这是目前文档中变更最密集、破坏性最强的版本。5.0.0 围绕“文档内容管理”做了多项 API 层面的 breaking change,涉及内容端点的重命名、新增与移除,以及 AI 配置项的全面更名。

内容端点重命名:content → formatted-content

原端点 /api/v1.0/documents/{document_id}/content/(返回格式化内容)已改名为:

/api/v1.0/documents/{document_id}/formatted-content/

从 视图实现 可以看到该端点的行为:它通过 content_format 查询参数控制输出格式,取值仅支持 json、markdown、html 三种,默认 json。实现逻辑是把存储在 S3 中的 base64 编码的 Yjs 内容解码后,调用格式转换服务输出对应格式:

  • content_format=json:输出结构化 JSON
  • content_format=markdown:输出 Markdown
  • content_format=html:输出 HTML

文档详情响应中移除 content 属性

在 /api/v1.0/documents/{document_id}/ 的响应体中,不再包含 content 属性。内容获取与更新被拆分为两个独立的专用端点,职责更清晰:

  • 新增 GET /api/v1.0/documents/{document_id}/content/:获取文档原始内容,以 text/plain 的 Content-Type 流式返回(streaming)整个内容。从源码 content_retrieve 可以看出,该端点直接从 S3 读取文档内容对象(get_object)并通过 StreamingHttpResponse 分块输出,同时实现了完整的 HTTP 条件缓存:

    • 基于 ETag 与 Last-Modified 头做缓存协商:请求携带 If-None-Match(ETag 一致)或 If-Modified-Since 时,命中则返回 304 Not Modified,避免重复传输内容。
    • 响应头中显式设置 ETag、Last-Modified、Content-Length 与 Cache-Control: private, no-cache。
    • 元数据(etag / last_modified)会写入缓存(key 由 utils.get_content_metadata_cache_key 生成,超时由 CONTENT_METADATA_CACHE_TIMEOUT 控制),后续请求可先在缓存中快速判定是否 304,避免每次都访问 S3。
    • 值得注意的实现细节:在发起 S3 调用前会主动 connection.close() 关闭数据库连接,因为 S3 取数耗时期间数据库连接无用,这样可避免 WebSocket 重连风暴期间数据库连接数暴涨。
    • 当文档内容在 S3 中不存在(NoSuchKey/404)时,返回一个空内容的 200 流式响应,保证客户端不会拿到错误状态。
  • 新增 PATCH /api/v1.0/documents/{document_id}/content/:更新文档原始内容,期望的请求体为:

{
  "content": "document content in base64"
}

从源码 content action 可以看到其完整处理链路:

  1. 使用 DocumentContentSerializer(见 serializers.py)校验请求,content 为必填字符串,且必须能通过 base64 解码校验,否则返回 400 校验错误。
  2. 请求体还支持一个可选的 websocket 布尔字段(write_only),当 COLLABORATION_WS_NOT_CONNECTED_READ_ONLY 设置开启且用户无编辑权限(且非 WebSocket 通道)时,会拒绝该 PATCH 请求(403)。
  3. 对内容做附件(attachment)提取:调用 extract_attachments 解析新内容引用的附件,结合 document.attachments 与当前用户可读的文档树(readable_per_se),只保留用户有权限读取的新附件,防止越权引用附件。
  4. 写入 document.content 并保存,同时删除内容元数据缓存,使下一次 GET 能拿到最新 ETag。
  5. 成功时返回 204 No Content。

该 PATCH 端点专门用于写入存储在 S3 中的原始 Yjs 内容,适合外部系统或脚本以编程方式整体替换文档内容。

废弃端点移除:/descendants

废弃端点 /api/v1.0/documents/<document_id>/descendants 已被移除,官方建议改用搜索端点(search endpoint)来实现原有“获取后代文档列表”的需求。

依赖升级:docspec >= 3.0.0

docspec 依赖必须升级到 3.0.0 及以上。UPGRADE.md 明确说明:docspec 服务自 3.0.0 起行为发生变化,Docs 5.0.0 只兼容 3.x,不再兼容 2.x。这属于强制的依赖版本跳跃,升级时务必同步更新镜像或锁文件。

AI 配置项更名与 Mistral SDK 支持

5.0.0 起,AI 特性支持通过 Mistral SDK 而非 OpenAI SDK 对接供应商。如果你的 AI 提供方兼容 Mistral API,官方鼓励优先使用 Mistral SDK。

伴随 SDK 支持,两个旧的环境变量被重命名:

旧变量名 新变量名 用途
AI_API_KEY OPENAI_SDK_API_KEY 仅用于配置 OpenAI SDK 的 API Key
AI_BASE_URL OPENAI_SDK_BASE_URL 仅用于配置 OpenAI SDK 的基础 URL

从 settings.py 的源码看,这两个新设置都保留了向后兼容的回退逻辑:OPENAI_SDK_API_KEY 会先读 OPENAI_SDK_API_KEY,若未设置则回退读取旧的 AI_API_KEY;OPENAI_SDK_BASE_URL 同理回退到 AI_BASE_URL。也就是说,5.0.0 阶段即使不立即改环境变量名也不会立刻失效,但建议尽快迁移到新名字,以便后续版本彻底移除旧名。

同时新增了 Mistral 侧的同构配置:

  • MISTRAL_SDK_API_KEY(SecretFileValue)
  • MISTRAL_SDK_BASE_URL

settings.py 中还有一个关键约束(settings.py#L1278-L1280):OPENAI_SDK_API_KEY 与 MISTRAL_SDK_API_KEY 不能同时设置,二者只能二选一,否则会在启动时抛出异常。

4.6.0(2026-02-27):主题配置接管 favicon 与 logo

4.6.0 对自定制外观的设置做了调整:覆盖 favicon 和 logo 现在统一通过主题配置完成,不再使用此前的独立设置方式。

主题配置的默认值定义在 default.json 中,其中 header 与 favicon 两个区块负责品牌元素:

  • header.logo:页头 Logo 配置
  • favicon:站点图标配置(仓库默认引用 /assets/favicon-light.png 与 /assets/favicon-dark.png,分别对应明暗主题)

如果你之前通过其他方式自定义了 favicon 或 logo,升级到 4.6.0 后需要把这些配置迁移到主题定制文件中,并通过 THEME_CUSTOMIZATION_FILE_PATH 环境变量指向该文件。

4.0.0(2025-11-26):设计系统升级与页头 Logo 结构变更

4.0.0 将 @gouvfr-lasuite/ui-kit 升级到 0.18.0。如果你在使用 CSS layer 或自定义模板定制 Docs 界面,必须同步更新你的定制内容以适配新的设计系统结构。

尤其要注意:如果你通过 THEME_CUSTOMIZATION_FILE_PATH 覆盖了页头 Logo,需要按新结构重写定制文件。新结构将 Logo 收敛到 header.icon 节点下,包含 src、width、height 三个字段:

{
  "...": "",
  "header": {
    "icon": {
      "src": "your_logo_src",
      "width": "your_logo_width",
      "height": "your_logo_height"
    }
  }
}

这一结构同样反映在 default.json 的 header 区块中,可作为新结构的最佳参照。

3.3.0(2025-05-22):MIT 兼容构建与可配置 Footer

3.3.0 有两个重要变更:

PUBLISH_AS_MIT:剔除 AGPL 依赖的高级特性

Docs 的部分高级功能(例如 Export as PDF)依赖 BlockNote 的 XL 包,这些包基于 AGPL-3.0 许可,与 MIT 不兼容。如果不需要这些功能,可以通过设置环境变量 PUBLISH_AS_MIT=true 构建一个不包含非 MIT 兼容特性的镜像:

PUBLISH_AS_MIT=true

README 中也特别强调了这一点(见 README.md 的 Self-hosting 章节):以该方式构建的镜像不含非 MIT 特性。相关环境变量的完整说明可参阅 环境变量文档。

Footer 可配置化

Footer 现在可以通过定制文件配置。使用 THEME_CUSTOMIZATION_FILE_PATH 环境变量指向你的定制文件(必须是一个符合主题定制规则的 JSON 文件)即可覆盖默认 Footer。主题定制的详细规则参见 主题定制文档。主题文件还支持缓存超时配置 THEME_CUSTOMIZATION_CACHE_TIMEOUT(见 settings.py#L579-L587)。

3.0.0(2025-03-28):协作服务器鉴权架构调整

3.0.0 对协作服务(yProvider)的访问控制做了一次架构层面的调整:

  • 不再使用 nginx auth request 机制来保护协作服务器。此前通过 nginx 反向代理层做鉴权校验的架构被移除,鉴权现在直接由 yProvider 服务器自己管理。
  • 因此,如果你在 Kubernetes 中使用 Ingress 注解,必须移除 ingressCollaborationWS 上的 nginx.ingress.kubernetes.io/auth-url 注解,否则协作 WebSocket 的访问会被旧的鉴权链路拦截或报错。

这一变化的含义是:yProvider 服务器必须能够直接访问 Django 服务器,以便自行完成鉴权与授权校验。为此需要给 yProvider 服务设置环境变量:

COLLABORATION_BACKEND_BASE_URL=<yProvider 服务可访问的 Django 地址>

从 y-provider 源码 可以看到该变量的默认值为 http://app-dev:8000(开发环境),而在 collaborationBackend.ts 中,它被用来拼接所有访问 Django 后端的请求路径(例如校验链接可达性 link_reach、collaboration_auth、media_auth 等权限判断接口)。此外,y-provider 通过 middlewares.ts 校验 authorization 请求头中的 API Key(对应 Y_PROVIDER_API_KEY),未携带或无效则返回 401——这是新鉴权体系的一部分。

也就是说,3.0.0 升级后需要同时完成两件事:删除 nginx 层的 auth-url 注解,并确保 yProvider 能通过 COLLABORATION_BACKEND_BASE_URL 反向访问 Django 完成鉴权。

2.2.0(2025-02-10):AI 功能仅限已认证用户

2.2.0 收紧了对 AI 功能(改写、总结、翻译、纠错等)的访问控制:

  • 在此版本之前,即使匿名用户只要通过 link reach(链接共享)获得了文档的编辑权限,也能使用 AI 功能。
  • 从 2.2.0 开始,AI 功能默认只对已认证(登录)用户开放。
  • 如果希望匿名用户继续使用 AI 功能,必须显式将 AI_ALLOW_REACH_FROM 设置为 "public"。

从 settings.py#L856-L862 可以看到该设置的可选值与默认值:

AI_ALLOW_REACH_FROM = values.Value(
    choices=("public", "authenticated", "restricted"),
    default="authenticated",
    environ_name="AI_ALLOW_REACH_FROM",
    environ_prefix=None,
)

即取值仅限 public、authenticated、restricted 三种,默认 authenticated。与之配套的 AI 功能总开关为 AI_FEATURE_ENABLED(默认 false,关闭时所有 AI 特性不可用),以及两个实现开关:

  • AI_FEATURE_BLOCKNOTE_ENABLED(默认 false):基于 BlockNote 的 AI 工具栏/AI 光标,UI 更丰富但依赖 AGPL 许可的 BlockNote 包,启用前需评估许可合规。
  • AI_FEATURE_LEGACY_ENABLED(默认 true):旧的“选区即上下文”AI 交互,功能较少但更稳定,且为 MIT 友好许可。

生产环境示例见 env.d/production.dist/backend,其中给出了 AI_BASE_URL、AI_API_KEY、AI_MODEL 的注释示例——注意在 5.0.0 之后它们应分别迁移到 OPENAI_SDK_BASE_URL 与 OPENAI_SDK_API_KEY。

升级检查清单

综合 UPGRADE.md 全文,一次完整的跨版本升级可以按如下顺序自查:

  1. 确认升级顺序:从当前版本逐级升级,不跳 minor/major;升级到 5.0.0 前需先经过 4.6.0、4.0.0、3.3.0、3.0.0、2.2.0 对应的配置迁移。
  2. 执行数据迁移:在容器内运行 python manage.py migrate(开发环境用 make migrate)。
  3. 检查 API 调用方(5.0.0):将 /content/ 的读取调用迁移到 /formatted-content/(携带 content_format 参数)或新的 GET /content/(流式原始内容);更新逻辑改用 PATCH /content/ 并提交 base64 内容;移除对 /descendants 的依赖,改用搜索端点;从文档详情响应中移除对 content 字段的读取。
  4. 升级依赖(5.0.0):确保 docspec 版本 >= 3.0.0。
  5. 迁移 AI 环境变量(5.0.0):AI_API_KEY → OPENAI_SDK_API_KEY、AI_BASE_URL → OPENAI_SDK_BASE_URL;如需 Mistral 兼容供应商,改用 MISTRAL_SDK_API_KEY/MISTRAL_SDK_BASE_URL,且不要同时配置两套 SDK Key。
  6. 迁移主题定制(4.6.0 / 4.0.0 / 3.3.0):favicon 与 logo 迁移到主题配置;按新结构(header.icon.src/width/height)重写页头 Logo;Footer 改用 THEME_CUSTOMIZATION_FILE_PATH 定制;适配 @gouvfr-lasuite/ui-kit 0.18.0 的设计系统结构。
  7. 处理许可敏感特性(3.3.0):如无 AGPL 特性(如 PDF 导出)需求,可设 PUBLISH_AS_MIT=true 构建镜像。
  8. 调整协作鉴权(3.0.0):删除 ingressCollaborationWS 上的 nginx.ingress.kubernetes.io/auth-url 注解,并为 yProvider 设置 COLLABORATION_BACKEND_BASE_URL 指向 Django 服务,确认 Y_PROVIDER_API_KEY 配置正确。
  9. 复核 AI 访问范围(2.2.0):如需匿名用户可用 AI,将 AI_ALLOW_REACH_FROM 显式设为 "public",否则保持默认 "authenticated"。

完成以上步骤后,即可在目标版本上验证文档读写、协作编辑、AI 功能与主题展示是否正常。由于 Docs 强调数据自主托管与实时协作,升级前建议先在测试环境完整演练一遍,再对生产实例执行迁移。

登录后查看全文
docs