Wagtail 2.12 版本解析:媒体 choose 权限、StreamField 原地更新与管理界面主题色定制
【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail
本文基于 Wagtail 2.12 官方发布说明(docs/releases/2.12.rst,发布于 2021 年 2 月 2 日)展开,梳理该版本引入的三大重点能力——图片/文档的独立 “choose” 权限、StreamField 值在 Python 代码中的原地更新、以及基于 CSS 自定义属性的管理后台品牌色定制——并逐一结合当前仓库的源码实现说明其底层机制。读完后你将了解这些功能的使用方式、配套的升级注意事项(Elasticsearch 2 支持与stream_data弃用),以及每项特性在代码中的对应位置,便于在升级或定制 Wagtail 时做出准确判断。
版本概览:2.12 带来了什么
Wagtail 2.12 于 2021 年 2 月 2 日发布,是 Wagtail 2.x 系列中一个以“细粒度权限 + 数据模型可操作性 + 主题定制”为亮点的小版本。发布说明将内容分为四部分:
- 三大新功能:图片/文档 choose 权限、StreamField 原地更新、管理后台颜色主题;
- 其他特性:Python 3.9 支持、图片/文档表单基类设置项、SVG 分页图标等 9 项改进;
- 缺陷修复:8 项 UI 与行为修复;
- 升级注意事项:移除 Elasticsearch 2 支持、弃用
StreamValue.stream_data属性。
下面按发布说明的原始结构逐项展开,并在每个功能后补充源码级证据。
新功能一:图片与文档的 choose 权限
功能说明
图片(Images)和文档(Documents)自本版本起支持独立的choose权限类型。它控制的是:在页面编辑中插入图片或文档时,选择器界面(chooser)里允许展示哪些素材。由此可以实现“某些集合(Collection)仅供特定用户组选用”的场景——例如市场部门可以上传素材到私有集合,而内容编辑者在选择器中只能看到公共集合里的内容。
该特性由 Robert Rollins 开发。
源码实现佐证
该权限落在集合权限策略中。wagtail/permission_policies/collections.py 的user_has_permission方法中,choose被作为一个与add、change并列的合法动作处理:
def user_has_permission(self, user, action): if action == "add": return self._check_perm(user, ["add"]) elif action == "choose": return self._check_perm(user, ["choose"]) elif action == "change" or action == "delete": # having 'add' permission means that there are *potentially* # some instances they can edit (namely: ones they own) return self._check_perm(user, ["add", "change"])在实例级的过滤逻辑instances_user_has_any_permission_for(同文件)中可以看到 choose 语义的核心规则:
当 actions 中包含
"choose"时,返回“位于(某后代)集合中、且用户对该集合拥有 choose 权限”的所有实例;与 change/add 的过滤结果按“任一权限”合并。
也就是说,choose 权限按集合(Collection)粒度授予,并自动作用于集合的后代层级,这正是“限定某些集合只能被特定用户组选用”能成立的机制基础。
权限本身是通过数据迁移为图片、文档的集合权限体系注册的,对应迁移文件:
- wagtail/images/migrations/0023_add_choose_permissions.py
- wagtail/documents/migrations/0011_add_choose_permissions.py
这两个迁移中的get_choose_permission辅助函数会在数据库层创建名为 “choose” 的权限对象,并在集合权限记录中初始化对应关系——升级后在后台“用户和群组”的集合权限界面即可看到新的 choose 勾选项。
新功能二:StreamField 值支持原地更新
功能说明
自 2.12 起,StreamField 的值正式支持从 Python 代码原地更新:可以直接对块(block)进行插入、修改和删除,而不必像以往那样重新构造一个完整的块列表再整体赋值给字段。详细用法参考官方文档 docs/topics/streamfield.md(modifying_streamfield_data章节)。该特性由 Matt Westcott 开发。
源码实现佐证
实现的核心是StreamValue类。在 wagtail/blocks/stream_block.py 中:
class StreamValue(MutableSequence):StreamValue继承自 Python 标准库的MutableSequence,从而天然获得可变序列语义。其后实现的关键成员包括(wagtail/blocks/stream_block.py):
__getitem__/__setitem__/__delitem__/insert:支持按索引读取、替换、删除块,以及在指定位置插入新块;raw_data属性:以原始 JSON 风格表示返回数据(见下一节的升级注意事项,它是stream_data的替代);get_prep_value:将当前的 BoundBlock 表示转换为可持久化的数据库格式。
MutableSequence意味着page.body[0] = new_block、page.body.insert(1, block)、del page.body[2]这类写法可以直接工作。需要注意的语义边界是:一旦访问过某个位置的 BoundBlock 表示,再回头修改raw_data中该位置的字段,不会反向传播到 BoundBlock,也不会被get_prep_value保存——这是源码注释中明确说明的兼容旧代码的折中行为,编写脚本时应遵循“要么走 BoundBlock,要么走 raw_data”的单一路径。
新功能三:管理后台颜色主题
功能说明
Wagtail 管理后台自本版本起,其主色调(teal 青绿色)改为使用CSS 自定义属性(CSS custom properties)承载。带来的直接收益:
- 为整个后台界面应用品牌色,只需几行 CSS;
- 第三方扩展可以复用 Wagtail 暴露的 CSS 变量,从而以相同的深度支持主题定制,而无需重写组件样式。
官方说明参考custom_user_interface_colors章节,当前仓库中该主题散见于 docs/advanced_topics/customization/admin_templates.md 等定制文档。该特性由 Joshua Marantz 开发。
实践方式
从源码组织看,后台样式位于 wagtail/admin/static_src/,而管理端前端资源主体在 client/scss/ 目录(采用 SCSS 组织,含settings、components、overrides等分层)。品牌色定制的典型做法是通过站点自身的 CSS 覆盖 Wagtail 的根级颜色变量,配合wagtail.admin_url_finder加载静态资源或在wagtail_hooks中注入<style>/静态文件。由于变量集中在少数自定义属性上,覆盖变量即可全局生效——这正是发布说明中“只需几行 CSS”的依据。
其他特性逐项说明
发布说明列出的其余改进,逐条整理如下(括号内为贡献者):
| 特性 | 说明与源码位置 |
|---|---|
| Python 3.9 支持 | 版本层面新增对 CPython 3.9 的解释器支持。 |
WAGTAILIMAGES_IMAGE_FORM_BASE/WAGTAILDOCS_DOCUMENT_FORM_BASE设置(Dan Braghis) | 允许自定义图片、文档的上传/编辑表单基类。实现见 wagtail/images/forms.py 的get_image_base_form:当设置项为 Django 导入路径字符串时,用import_string加载自定义表单类替代默认的BaseImageForm。文档侧为对称实现。测试用例见 wagtail/images/tests/test_form_overrides.py,其中用AlternateImageForm验证了覆盖生效。 |
| 分页图标改用 SVG | 分页控件由图标字体切换为内联/引用 SVG,消除字体图标依赖(Scott Cranfill)。 |
图片Format类增加字符串表示(Andreas Nüßlein) | 调试时打印Format对象可读性提升。 |
register_page_action_menu_item/register_snippet_action_menu_item可返回None跳过注册(Vadim Karpenko) | 扩展可在运行时条件性注册菜单项。 |
自定义图片模型的字段可定义为必填(blank=False)(Matt Westcott) | 放宽了此前对自定义 Image 模型字段校验的限制。 |
| Postgres 搜索后端增加组合索引(Will Giddens) | 搜索性能优化,作用于 Postgres 全文检索后端的索引结构。 |
Page.specific_deferred属性(Andy Babic) | 获取当前页面对应具体子类实例而不发起前置数据库查询。实现见 wagtail/models/specific.py:它调用self.get_specific(deferred=True),返回结果缓存在内存中,用于避免specific属性触发的一次额外查询。 |
| embeds 增加哈希查找(Coen van der Kamp) | 为嵌入 URL 增加基于哈希的索引,支持超过 255 字符的长 URL(受Embedding模型 URL 字段长度限制驱动)。 |
缺陷修复
2.12 一并修复了以下 8 个问题:
- 页面编辑器在小视口宽度下,菜单图标与面包屑重叠(Karran Besen);
- 文档选择器翻页时未保持已选中的集合(Alex Sa)——这与本版本的集合权限体系直接相关;
- oEmbed 端点返回非 JSON 响应时无法优雅处理(Matt Westcott);
WorkflowState唯一约束与 SQL Server 不兼容(David Beitey);- 集合下拉框缺失展开箭头(chevron)(Mike Brown);
- 集合/工作流编辑视图中,即使用户没有删除权限仍显示删除按钮(Helder Correia);
- 图片格式选择器中,表单标签移到字段上方,修复平板尺寸下的样式问题(Helen Chapman);
{% include_block with context %}现在会将局部变量传入块模板(Jonny Scholes)——这是一个模板级行为变更,依赖旧行为(模板内拿不到局部变量)的自定义块模板需要留意。
升级注意事项
1. 移除对 Elasticsearch 2 的支持
自本版本起,Elasticsearch 2 不再受支持。如果你的站点仍在使用 Elasticsearch 2 作为搜索后端,必须先升级到 Elasticsearch 5 及以上版本,再进行 Wagtail 升级。这是 2.12 升级前唯一硬性阻断项。
2.StreamValue.stream_data属性弃用
stream_data属性常被用来访问 StreamField 的底层数据,但它是一个未公开的内部属性,且存在一个隐蔽的坑:同一数据,无论其来源是数据库还是内存,表示形式可能不同——未妥善处理时会在预览(preview)场景下出错。因此 2.12 正式将其标记为弃用。
官方推荐两种替代写法:
推荐方式一:把 StreamField 值直接当作列表索引
# 旧写法(依赖 stream_data) page.body.stream_data[0]['type'] page.body.stream_data[0]['value'] # 新写法(直接索引 StreamValue) page.body[0].block_type page.body[0].value直接索引的优势是:返回的 Python 对象与模板中渲染 StreamField 时一致——例如PageChooserBlock会返回真正的Page实例,而不是字典。
推荐方式二:使用新的raw_data属性作为stream_data的等价替换
大多数既有代码期望的是“原始 JSON 风格”的数据表示,对这类代码,2.12 新增的raw_data属性(见 wagtail/blocks/stream_block.py)可以原样替换stream_data:
# stream_data 与 raw_data 的原始表示等价,属于 drop-in 替换 page.body.raw_data[0]源码中对兼容性的处理也印证了这一点:StreamValue内部的_RawData视图类注释明确说明,其可变性是为了“兼容旧代码曾直接操作StreamValue.stream_data的用法”,并约束了 BoundBlock 与 raw data 之间的单向传播规则(见前文“实践边界”)。
升级建议:新代码一律使用列表索引或raw_data;存量代码可将stream_data直接改为raw_data以最小代价消除弃用警告,之后再逐步把能改造成 BoundBlock 索引的热点路径迁移过去。
小结
Wagtail 2.12 是一个“小版本、大纵深”的发布:choose 权限把集合权限模型扩展到了“选用”这一新维度(wagtail/permission_policies/collections.py 中add/choose/change三动作的对称处理是理解入口);StreamValue成为MutableSequence(wagtail/blocks/stream_block.py)让内容模型在 Python 侧可增量操作;CSS 自定义属性则把主题定制从“重写组件样式”降维为“覆盖变量”。升级时只需确认两件事:搜索后端是否为 Elasticsearch 5+,以及代码中是否仍在使用stream_data。更多背景可参考本版本发布说明 docs/releases/2.12.rst 及 StreamField 专题文档 docs/topics/streamfield.md。
【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考