页面发布

Odoo 官网页面为什么不是“改个 URL 就上线”:发布、菜单、首页与旧链接回收主链路讲透

很多人把 Odoo 页面管理理解成“建一个 page,再改个链接”,但 website.page 与 website.page.properties 实际把发布时间、菜单绑定、首页切换、索引控制与旧 URL 回收串成了一套完整治理链路。

网站
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

在 Odoo 里,一个官网页面不是“有个 URL 的 HTML 片段”这么简单。

/home/ubuntu/odoo-temp/addons/website/models/website_page.pywebsite_page_properties.py 看,页面背后至少同时挂着这几件事:

  • 页面视图本体 ir.ui.view
  • 对外 URL;
  • 发布状态和定时发布时间;
  • 是否加入菜单;
  • 是否作为首页;
  • 是否允许搜索引擎索引;
  • 改 URL 后要不要给旧地址留跳转。

所以更准确的理解应该是:

Odoo 的页面管理,本质上是在管“一个公开入口的生命周期”,不是只管一段内容。

这也是为什么很多团队改版官网时,真正容易出错的不是编辑内容,而是:

  • 页面看起来发布了,前台却不出现;
  • 菜单改了但首页没跟着变;
  • URL 改完旧外链全断;
  • 页面还没到发布时间就提前暴露或完全找不到。

一、website.page 为什么不是普通内容表,而是 ir.ui.view 的外壳

website.page 用了 _inherits = {'ir.ui.view': 'view_id'}

这说明页面本体并不是一个独立的 HTML blob,而是建立在 QWeb 视图之上的“网站页外壳”。

这样做的好处很明确:

  1. 页面天然吃到视图体系的继承、渲染和缓存能力;
  2. 页面仍然可以保留网站层面的 URL、菜单、发布时间等额外治理属性;
  3. 删除页面时,系统还能判断这个 view 是否只被这一页使用,再决定是否连带清理。

所以页面删除逻辑里会专门处理:

  • 如果这个 view 只属于当前页面且没有继承子项,就一起删;
  • 否则不能粗暴清理。

这不是小题大做,而是在避免把视图层公共资产顺手删掉。


二、页面“可见”为什么不只看 website_published

很多人以为页面可见性只取决于一个布尔值。

website.page_compute_visible() 很明确:

  • 要先 website_published = True
  • 还要满足 date_publish 为空,或者已经早于当前时间。

也就是说,前台可见性的本质是:

发布开关 + 发布时间窗口。

这套设计很适合官网改版、专题页预热、活动页预约上线。

但它也带来一个很常见的误区:

  • 后台已经勾了 Published,
  • 结果前台还看不到。

很多时候不是缓存问题,而是 date_publish 还没到。

如果你把“是否已发布”和“何时允许曝光”拆开理解,很多看似诡异的现象就很容易解释。


三、为什么页面 URL 变化时,菜单与首页都要一起跟着考虑

website.page.write() 在处理 URL 时,不只是改页面自己的 url 字段。

源码还会做三件事:

  1. 把新 URL 做 slugify;
  2. 通过 get_unique_path() 确保路径不冲突;
  3. 同步更新相关菜单的 URL;
  4. 如果这个页面原来就是首页,还要连带处理 homepage_url

这里很能体现 Odoo 的页面观:

  • 页面 URL 不是一个孤立字段;
  • 它牵着菜单、首页映射和缓存。

所以页面换链接,本质上是在改一个公开入口的地址主键。系统必须把围绕它的一圈引用也一起整理。


website.page.properties.base 里有一组很实用的逻辑:

  • menu_ids
  • is_in_menu
  • _inverse_is_in_menu()

这套代码的意思很简单:

  • 你在页面属性里勾“加入菜单”,系统会自动创建对应 website.menu
  • 取消勾选时,系统会按 page_id 或 URL 域去找相关菜单并删除。

而且源码还特别注意了 URL 变更场景:

  • website.page,优先按 page_id 找菜单;
  • 对其它对象,再退回按 URL 找。

这个细节很重要。

因为 URL 是会变的,而 page_id 更稳定。Odoo 明显是在避免“页面改过地址以后,原菜单挂不上或删不掉”的老问题。


五、为什么首页切换不是简单把 URL 改成 /

很多 CMS 把首页理解成“那一页的地址是 /”。

Odoo 不是。

website.page.properties 里,首页的核心是网站记录上的:

  • website.homepage_url

这意味着首页不是页面自己自称“我是 /”,而是:

网站把哪个 URL 认作自己的首页入口。

这样设计有两个明显好处:

  1. 页面本身可以保留自己的真实 URL;
  2. 首页映射可以换,而不必强行让某个页面只能叫 /

这对后续改版非常友好。

比如你想把首页从旧专题切到新 landing page,不一定要重建页面结构,只要调整 homepage 入口映射即可。


六、为什么页面属性里会顺手带上索引控制与旧链接回收

website.page.properties 不只是编辑标题和 URL。

它还带着:

  • website_indexed
  • redirect_old_url
  • redirect_type

这说明在 Odoo 的产品观里,页面编辑和 SEO/流量治理是连在一起的。

1. website_indexed

这是在控制:

  • 页面是否应该进入可被网站搜索和索引的范围。

它不是是否公开可见的唯一条件,但会影响搜索结果和站内可发现性。

2. redirect_old_url

当你修改页面 URL 时,如果勾选这个选项,write() 结束后会自动创建一条 website.rewrite 记录,把旧地址导向新地址。

这件事非常关键,因为官网改版时最贵的不是换文案,而是外链资产丢失:

  • 搜索引擎已收录旧地址;
  • 用户书签还在旧地址;
  • 外部文章、公众号、邮件都可能引用旧地址。

如果改链接时不顺手回收旧 URL,很多流量会被你自己切断。


七、为什么页面搜索、缓存和多网站特异性都和这套属性强绑定

website.page 里有几个容易被忽略但很要命的点。

1. 多网站下要找“最具体的页面”

_get_most_specific_pages() 会优先处理更具体的网站版本,避免共享页和站点特定页混淆。

2. URL / 可见性 / group 改动会清模板缓存

只要 URL、visibility 或 group_ids 变了,源码会 clear_cache('templates')

这说明页面访问结果明显依赖这些条件,不能继续吃旧模板缓存。

3. 搜索时也会再补一层权限和公开性边界

前台搜索页面时,非设计器用户只能看到:

  • 已发布;
  • 可索引;
  • visibility 不拦截;
  • group 权限允许。

所以“页面存在于库里”与“用户能搜索到它”本来就不是一回事。


八、最容易踩的坑,不是写页面,而是把页面当静态文件看

实施里最常见的几个误区:

误区一:Published 就一定能访问

不对,还要看 date_publish 与 visibility。

误区二:改了 URL,菜单自然会好

不一定。虽然 Odoo 会尽量同步,但你的自定义菜单、手写链接、站外入口不一定自动修好。

误区三:旧 URL 断了是正常的

这在运营上通常是坏实践。大多数正式改版,都应该至少评估是否启用旧地址重定向。

误区四:首页就是 /

在 Odoo 里,首页更像“网站默认入口映射”,不是页面自身身份。


九、实战里怎么用这套机制更稳

如果你正在做企业官网、专题页或长期内容站,我更建议按下面的方式操作。

1. 把页面视为“带生命周期的入口对象”

不要只盯正文和区块。

2. 上线前明确区分三件事

  • 是否发布;
  • 何时发布;
  • 是否可被索引。

这三个不是一件事。

3. 改 URL 时默认评估旧地址回收

特别是已有 SEO 积累或外部传播的页面。

4. 菜单是否展示,尽量走页面属性,不要全靠手工散配

这样后续迁移时一致性更高。

5. 首页切换优先理解为入口映射切换

别一上来就去重构整棵页面树。


结语

Odoo 官网页面的真正复杂度,不在“页面编辑器好不好用”,而在:

系统把页面当成一个长期公开入口来治理。

它要管内容、URL、时间、菜单、首页、索引和旧链接资产。

所以读懂 website.pagewebsite.page.properties 之后,你会发现 Odoo 页面管理最有价值的地方,不是拖拖拽拽,而是它已经默认把很多官网运营里最容易被忽视的“发布后问题”放进了模型层。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。