PAYATHON 2026

Odoo Website Checkout 跳转至 500 错误页面

支付老李

结论

500 错误出现在 QWeb 渲染 website_sale.address 时。该模板调用了:

<t t-call="website_sale.cart_summary"/>

但当前网站(website_id = 1)无法解析外部 ID website_sale.cart_summary,导致 Checkout 在地址页面中断,还没有进入支付方式选择阶段。

管理员可以正常结账,并不代表问题出在支付权限上。更常见的原因是管理员已经填写了完整的联系人和地址信息,因此 Checkout 跳过了 /shop/address。访客和普通用户仍需渲染 website_sale.address,这时才会触发模板缺失错误。还有一种可能是该 View 被错误地限制为仅内部用户或特定用户组可用。

应优先恢复或修复 website_sale.cart_summary,同时检查 website_sale.address 是否被 Studio、主题或自定义模块错误修改。

常见原因

按大致出现概率排列,常见原因包括:

  1. Website 或 Studio 自定义删除、停用或覆盖了模板

    错误页面已经出现“Restore previous version”和“Reset to initial version”,说明 website_sale.address 很可能有网站编辑器或 Studio 留下的定制记录。

  2. website_sale 模块升级不完整

    数据库中的 View 可能与当前 Odoo 17 源码不一致。例如代码已经升级,但数据库模块没有同步升级。

  3. 自定义主题或模块覆盖了标准 Checkout 模板

    自定义模块可能继承或替换了 website_sale.address,同时调用了一个已被删除、改名或尚未加载的模板。

  4. 多网站作用域配置错误

    cart_summary 可能绑定到了其他网站,或者系统中存在冲突的网站专属副本,导致网站 1 无法找到可用版本。

  5. View 的用户组配置错误

    如果模板设置了内部用户或管理员组限制,管理员可以解析该模板,而 Public 或 Portal 用户无法使用。

  6. 外部 ID 丢失

    ir.ui.view 记录可能仍然存在,但 ir.model.data 中 website_sale.cart_summary 的映射已经被删除或损坏。此时不要直接新建同名 View,应先通过模块升级恢复标准数据关系。

建议的修复顺序

1. 先备份数据库

重置 View、升级模块或修改 XML 前,先备份数据库。尤其不要直接删除生产数据库中的 ir.ui.view 或 ir.model.data 记录。

2. 检查 website_sale.address 的定制

启用开发者模式,然后进入:

设置 → 技术 → 用户界面 → 视图

搜索以下外部 ID:

website_sale.address
website_sale.cart_summary

逐项检查:

  • website_sale.cart_summary 是否存在;
  • View 是否处于 Active 状态;
  • View 是否被错误绑定到其他 Website;
  • Groups 中是否包含仅供内部用户或管理员使用的组;
  • 是否存在多个同名或同 Key 的网站专属 View;
  • website_sale.address 的 Architecture 是否仍在调用正确的外部 ID;
  • 是否存在由 Studio、主题或自定义模块创建的继承 View。

如果错误页面提供了 View 重置功能,可以先对 website_sale.address 执行 soft reset。只有在确认现有定制不再需要时,才考虑 hard reset,因为硬重置会清除该 View 上的定制内容。

3. 升级 website_sale 模块

如果标准 View 或外部 ID 缺失,通常应该通过模块升级恢复,不要手工拼接不完整的 Checkout 模板。

自托管环境可以在维护窗口执行:

./odoo-bin -d DATABASE_NAME -u website_sale --stop-after-init

如果系统中有自定义主题或 Checkout 模块,还需要确认它们与 Odoo 17 兼容,并按依赖顺序升级。数据库名、配置文件和 Odoo 启动路径应根据实际部署方式调整。

Odoo.sh 或其他托管环境应使用平台对应的模块升级流程,不要直接修改平台管理的核心源码。

4. 检查外部 ID 和 View 状态

可以在 Odoo shell 中执行只读检查:

view = env.ref(
    "website_sale.cart_summary",
    raise_if_not_found=False,
)

view

如果结果是 None,说明该外部 ID 确实不存在。接着检查是否有同 Key 的 View:

env["ir.ui.view"].sudo().search([
    ("key", "=", "website_sale.cart_summary"),
]).read([
    "name",
    "key",
    "active",
    "website_id",
    "inherit_id",
    "groups_id",
])

再检查外部 ID 映射:

env["ir.model.data"].sudo().search([
    ("module", "=", "website_sale"),
    ("name", "=", "cart_summary"),
]).read([
    "module",
    "name",
    "model",
    "res_id",
])

根据结果采取相应处理:

  • View 和外部 ID 都不存在:升级 website_sale;
  • View 存在但 active=False:查明停用原因后恢复;
  • View 仅绑定到其他网站:修正 website_id,或恢复通用的标准 View;
  • View 带有不合理的 groups_id:移除 Checkout 公共模板上的内部用户限制;
  • 外部 ID 指向不存在的 res_id:说明数据不一致,应优先通过模块升级修复;
  • 存在多个网站专属副本:检查继承关系和网站优先级,避免错误副本遮蔽标准 View。

5. 检查自定义模板引用

如果自定义模块覆盖了地址页面,需要确认它调用的模板确实存在:

<template id="custom_checkout_address"
          inherit_id="website_sale.address">
    <!-- 自定义内容 -->
</template>

调用标准模板时,外部 ID 必须完全正确:

<t t-call="website_sale.cart_summary"/>

如果自定义模块将 cart_summary 替换成了自己的模板,该模板必须先于调用方加载。例如:

<odoo>
    <template id="custom_cart_summary"
              name="Custom Cart Summary">
        <div class="my_cart_summary">
            <!-- 实际摘要内容 -->
        </div>
    </template>
</odoo>

调用时应使用该模块真实的技术名称:

<t t-call="my_module.custom_cart_summary"/>

不要为了消除异常而新建一个空的 website_sale.cart_summary。购物车摘要可能涉及金额、税费、配送方式和订单状态。空模板或许能暂时绕过 500 错误,却可能掩盖更严重的 Checkout 数据问题。

为什么只影响访客和普通用户

可以分别测试以下路径:

访客 → 购物车 → Checkout → 地址页面
Portal 用户 → Checkout → 地址页面
已有完整地址的用户 → Checkout
管理员 → Checkout

如果管理员直接跳过地址页面,而访客在地址页面报错,说明不同的 Checkout 分支调用了不同模板。管理员权限本身并没有修复 View。

如果所有用户都会进入同一个地址页面,但只有管理员能够成功,应重点检查:

  • website_sale.cart_summary 的 groups_id;
  • 自定义继承 View 的用户组;
  • Public、Portal 用户的 View 可见性;
  • 自定义代码中基于 request.env.user 或 user.has_group() 的条件;
  • 网站专属 View 与缓存造成的差异。

修复后的验证

修复或升级完成后,应重启 Odoo 服务以清理进程内缓存,再使用无痕窗口重新测试。至少需要确认:

  • 未登录访客可以打开地址页面;
  • Portal 用户可以继续结账;
  • 配送地址和账单地址可以保存;
  • 页面可以进入 payment method 选择阶段;
  • 多网站环境中的其他网站没有受到影响;
  • 日志中不再出现 View 'website_sale.cart_summary' ... not found。

处理时应先恢复标准的 website_sale View 和外部 ID,再逐项重新应用主题或 Studio 定制。直接修改数据库记录或创建同名占位模板,只应作为最后手段,并且操作前必须明确现有的继承关系。

备注:内容仅供参考。