先说结论
很多人用 Odoo 网站编辑器时,会把动态 snippet 理解成一种“页面装修组件”:
- 拉一个模块上去;
- 选个模板;
- 自动显示几条博客、产品或活动;
- 然后事情就结束了。
但 website.snippet.filter 的源码告诉我们,事情远不止如此。
它真正解决的是一个官网运营里的核心问题:
哪些内容可以被公开展示、按什么规则展示、展示多少、跨网站时该不该看到。
也就是说,动态 snippet 本质上不是“前端样式能力”,而是 公开内容编排层。
一、为什么 snippet filter 不是数据源本身,而是“数据源适配器”
website.snippet.filter 支持两种来源:
filter_id:基于ir.filters的过滤器;action_server_id:基于ir.actions.server的服务端动作。
而且源码硬性要求:
- 两者必须二选一;
- 不能都没有;
- 也不能同时都填。
这说明 Odoo 很清楚一个事实:
动态内容的来源不止一种。
有些场景适合“标准搜索条件”:
- 最新博客;
- 已发布活动;
- 当前网站下的某类产品;
- 某行业客户案例。
另一些场景则更适合“服务端计算结果”:
- 混合多模型推荐;
- 特殊排序逻辑;
- 结合用户上下文的内容推荐;
- 需要复杂业务判断的首页卡片。
因此 snippet filter 不是内容本体,而是把不同数据源统一包装成可公开渲染的数据集。
二、为什么 Odoo 要对 limit 做硬限制,而且上限只有 16
源码中有个很有意思的约束:
limit必须在 1 到 16 之间;- 即便客户端想多拿,也会再套一层
max(self.limit, 16)的保护逻辑。
很多人看到这里会觉得“太死板”。
但从网站运营角度看,这反而非常合理。
因为动态 snippet 的位置,通常在:
- 首页;
- 栏目页头部;
- Landing page 中段;
- 博客、产品、活动等公开入口区域。
这些地方最怕的不是“内容太少”,而是:
- 一口气查太多数据;
- 页面首屏变重;
- 编辑器和前台取数边界不一致;
- 运营同学一不小心把首页变成列表页。
Odoo 用 limit 上限强行把它拉回“内容块”的角色,而不是放任它长成“万能查询器”。
这其实是在保护站点性能和信息密度。
三、为什么公开展示前还要再叠网站范围、公司范围和发布状态
_prepare_values() 里很关键的一段,是它会在 filter 域基础上继续补条件:
- 模型有
website_id时,只允许当前网站范围; - 模型有
company_id时,只允许无公司或当前网站公司; - 模型有
is_published时,只取已发布记录。
这三条补充约束,基本把官网内容编排的核心边界说透了。
1. 网站范围
多网站场景下,A 站首页不该莫名展示 B 站内容。
2. 公司范围
集团或多公司部署里,公开内容也要尊重公司归属。
3. 发布状态
后台有记录,不代表可以上官网。
这说明 Odoo 从来不把动态 snippet 当成“后台数据随便搬上前台”的工具。
它先问的是:
这条内容有没有资格成为公开内容。
四、为什么字段清单同样重要,它决定你公开了什么
field_names 是必填,而且连空字段名都会报错。
很多人会忽略这个点,以为它只是模板显示配置。
其实它影响的是:
- 你准备把哪些字段暴露给前台模板;
- 字段应该以文本、图片、金额还是别的 widget 方式解释;
- 样本数据如何自动补齐;
- 模板在渲染时能拿到多完整的内容结构。
这意味着 snippet filter 不只是在过滤记录,也是在控制“记录的公开投影”。
换个更直白的说法:
后台对象可以很复杂,但首页卡片只应该暴露一小部分、而且是可控的一小部分。
这就是为什么字段清单值得被单独配置,而不是让模板随意取整个对象。
五、为什么 Odoo 对“没有真实数据”也要准备 sample
_render() 里支持 with_sample,如果没有记录就会走 _prepare_sample()。
这在编辑器体验里非常重要。
因为网站编辑阶段经常处在一种尴尬状态:
- 模板先搭好了;
- 真实内容还没上线;
- 运营想先看版式;
- 前端想先调样式。
如果这时组件直接空掉,编辑器体验会很差。
Odoo 给 sample 的意义不是“造假数据”,而是让编排工作可以在真实内容准备完成之前先推进。
这也体现出它对网站工作流的理解:
- 内容生产
- 页面编排
- 样式验证
- 正式发布
这几个动作并不总是同步发生的。
六、为什么服务端 action 是把内容运营能力往前推的一步
当 snippet filter 走 action_server_id 时,Odoo 会把:
- 当前 dynamic_filter;
- limit;
- search_domain
放进上下文,再由 server action 返回结果。
这很值得重视。
因为它意味着动态内容块并不局限于标准列表模型,它可以成为一个更灵活的官网内容调度器:
- 首页推荐可以不是单表查询;
- 活动、博客、产品可以混编;
- 可根据 campaign、页面、来源做不同内容策略;
- 甚至可以做“编辑器可用、逻辑在后端”的定制能力。
这时候,snippet 就不再只是装修件,而是内容运营的执行器。
七、实战里最容易误解的地方
1. 动态 snippet 不等于推荐算法
它首先是公开内容过滤和展示机制,推荐只是其中一种玩法。
2. 能查到不等于能公开展示
网站、公司、发布状态边界必须同时满足。
3. 内容块不是列表页替代品
limit 的存在就是在阻止你把首页卡片做成“迷你后台搜索界面”。
八、给官网运营团队的建议
如果你们常用 Odoo 编辑首页和栏目页,最好把动态 snippet 当成“内容货架”来治理:
- 明确每个内容块的目的,是引导点击还是直接承载信息;
- 不要让一个 snippet 背后挂过于复杂的数据和字段;
- 多网站下检查 website_id 边界是否正确;
- 对 server action 型内容块保留文档,别让后期没人敢改;
- 不要为了“看起来丰富”把 limit 一路开满。
最后的结论
website_snippet_filter 真正做的,是把:
- 数据源选择、
- 公开范围约束、
- 字段投影控制、
- 数量限制、
- 前台渲染
串成一条完整链路。
所以 Odoo 动态 snippet 从来不是“拖一个组件上去”就结束。
它本质上是:
官网公开内容如何被挑选、裁剪、摆放和稳定展示的一层编排机制。
DISCUSSION
评论区