先说结论
Odoo 博客的“发布完成”,绝不是正文写好、封面上传、点一下 published 就结束。
从 website_blog/models/website_blog.py 与 website/models/website.py 看,博客发布实际至少同时受四层内容机制影响:
cover_properties决定页面首屏与社交图像来源;website.seo.metadata负责 title、description、Open Graph、Twitter 卡片等元数据;seo_name和 slug 共同影响 URL 长相;- 站点级 canonical URL 与语言本地化逻辑,决定搜索引擎最终应把哪条地址视为规范版本。
所以正确理解应该是:
一篇 blog post 在 Odoo 里是“内容对象 + 展示封面 + SEO 元数据 + 规范地址”的组合体。
只要把它当成单纯 CMS 正文页,SEO、分享卡片和多语言规范地址迟早会出问题。
一、为什么博客模型一上来就继承 cover 和 SEO mixin
blog.post 继承的 mixin 很说明问题:
website.seo.metadatawebsite.published.multi.mixinwebsite.page_visibility_options.mixinwebsite.cover_properties.mixinwebsite.searchable.mixin
这不是为了“功能多一些”好看,而是在定义博客对象的本质:
- 它不仅有正文;
- 它还必须可被网站搜索;
- 必须能控制发布可见性;
- 必须携带封面展示属性;
- 必须能产出适合搜索引擎和社交平台的元信息。
所以博客封面从一开始就不是装饰,而是内容分发链路的一部分。
二、为什么 cover_properties 不只是页面背景,而是分享图来源
_default_website_meta() 里有个特别关键的细节:
og:image与twitter:image直接从cover_properties的background-image里提取。
也就是说,很多人以为“封面只影响文章头图显示”,但源码实际上告诉我们:
- 这张图还会被拿去当社交分享图;
- 它会影响链接预览;
- 甚至会影响内容在聊天工具、社交网络里的第一印象。
这会带来两个很现实的运营后果:
1. 封面不是只给站内看的
如果封面裁切差、尺寸怪或引用异常,问题不只在页面首屏,也会体现在分享卡片上。
2. 封面字段和 SEO 图像字段并不是两条完全独立的线
在默认逻辑下,它们天然相连。
所以“页面好看但分享卡片不好看”,很多时候不是社交平台抽风,而是封面资产本身就没按分享场景设计。
三、为什么 subtitle 比很多人想的更像 SEO 核心字段
同一个 _default_website_meta() 里:
og:description用的是subtitle;twitter:description用的是subtitle;- 默认 meta description 也是
subtitle。
这说明在 Odoo 博客语义里,subtitle 不是可有可无的副标题,而更像:
给搜索引擎和分享渠道准备的一段简明内容说明。
如果团队只认真写正文,不认真写 subtitle,就会出现一种常见错觉:
- 页面内容明明不错;
- 但 Google 摘要、社交分享描述、预览文案都很平。
原因往往不是抓取失败,而是默认元描述压根就没有被运营化处理。
四、为什么 seo_name 和 blog/post slug 一起决定 URL 观感
_compute_website_url() 会把博客文章路径拼成:
/blog/<blog_slug>/<post_slug>
而 website/models/ir_http.py 又说明:
- 如果对象带
seo_name,slug 生成会优先利用它。
这意味着 Odoo 博客 URL 不是单一文章字段在起作用,而是:
- 博客容器 slug;
- 文章对象 slug;
- 以及可翻译、可编辑的
seo_name。
这就解释了为什么有些站点会碰到:
- 同一篇文章换语言后 URL 观感不同;
- 标题改了但旧链接还存在重定向需求;
- blog 本身的命名也会影响文章路径。
所以 URL 设计不是正文编辑完成后再临时想一下,而应该在栏目层和文章层一起规划。
五、为什么 canonical 是博客 SEO 最容易被忽略的一环
website._get_canonical_url() 会基于当前请求语言和站点 base URL,生成规范地址。
_is_canonical_url() 则用它来判断当前请求是不是规范版本。
这意味着 canonical 在 Odoo 网站里不是插件式附加功能,而是站点级路由语义的一部分。
它尤其影响两类问题:
1. 多语言地址
同一篇内容在不同语言、不同路径前缀下,搜索引擎应该把哪条当主版本。
2. 编码与地址标准化
源码还特别提到含可引用字符的路径,当前 URL 与 canonical URL 的比较会更谨慎。
这说明 canonical 问题不是只跟“有没有 <link rel=canonical>”有关,还跟:
- 当前请求 URL 是否标准;
- 多语言本地化路径是否一致;
- 域名和 base URL 是否统一。
六、为什么“已发布”仍然可能不是一个稳定的 SEO 成品页
即使 website_published = True,一篇博客也不必然已经具备理想的搜索和分享表现。
你还得同时确认:
subtitle是否适合作为默认 description;cover_properties是否能产出合格分享图;seo_name是否稳定、可读、适合长期保留;- canonical 是否落在预期语言和域名上;
- 站点是否用统一 base URL 输出规范链接。
也就是说,发布状态解决的是“能不能看见”,SEO / canonical 解决的是“应该怎样被看见”。
最后给内容站运营者的 4 个提醒
1. 把 subtitle 当成 SEO 资产来写
别把它当副标题填空题。
2. 封面图要按社交分享场景设计
否则首屏能看,不代表卡片能看。
3. URL 规划要同时考虑 blog 与 post 两层 slug
别只盯单篇文章。
4. 多语言博客上线前一定检查 canonical
否则很容易把搜索权重分散到多个地址上。
参考源码
addons/website_blog/models/website_blog.pyaddons/website/models/website.pyaddons/website/models/ir_http.py
DISCUSSION
评论区