Odoo 13 如何通过代码为配置HTML组件的字段插入表格行
问题根因定位
你遇到的HTML不渲染、内容被自动包裹为<p>标签显示为纯文本,核心是两个配置和逻辑不匹配的问题:
- 后端字段类型与前端组件要求不匹配:前端
widget="html"是富文本渲染组件,对应存储字段如果是fields.Char(纯文本存储类型),存储层会自动将所有HTML字符转义为实体字符,前端拿到的内容本身就是转义后的纯文本,自然无法正常渲染。 - 富文本编辑器的默认规范化逻辑触发:Odoo内置的富文本组件会自动对非结构化输入做格式修正,比如把零散文本自动包裹
<p>标签、将不在白名单内的HTML标签转义为纯文本,你之前直接写入的文本形式HTML,因为没有被识别为合法结构化HTML,就会被这套逻辑处理成普通段落文本。
可落地的解决步骤
1. 修正后端字段定义
将原有的纯文本Char字段替换为支持富文本的Html字段,同时关闭会拦截表格标签的默认清洗逻辑,代码如下:
# 替换原test_field定义 test_field = fields.Html( string='Test', sanitize=False, # 关闭默认HTML标签清洗,避免<table>等结构被过滤 strip_style=False, # 保留标签内联样式,避免渲染格式丢失 sanitize_attributes=False # 保留标签属性,避免样式相关属性被移除 )
如果需要保留基础XSS防护能力,不需要全局关闭sanitize,可以在配置中单独添加允许的标签白名单,将table、thead、tbody、tr、td、th等表格相关标签加入白名单即可。
2. 分场景完成带指定值的表格行写入
后端Python逻辑写入场景
直接拼接完整的合法HTML表格结构,通过write方法赋值即可,不要传转义后的HTML字符串(比如不要把<写为<),示例代码:
# 拼接带指定值的表格内容 target_table_html = """ <table style="width: 100%; border-collapse: collapse; margin: 8px 0;"> <thead> <tr> <th style="border: 1px solid #e0e0e0; padding: 6px 8px;">列头1</th> <th style="border: 1px solid #e0e0e0; padding: 6px 8px;">列头2</th> </tr> </thead> <tbody> <tr> <td style="border: 1px solid #e0e0e0; padding: 6px 8px;">第一行指定值</td> <td style="border: 1px solid #e0e0e0; padding: 6px 8px;">第二行指定值</td> </tr> </tbody> </table> """ # 直接赋值给目标字段 self.write({'test_field': target_table_html})
写入完成后,富文本组件会识别到这是合法结构化HTML,不会自动给内容包裹多余的<p>标签,也会正常渲染表格结构。
前端JS逻辑插入表格行场景
不要直接操作DOM设置textContent写入内容,要调用富文本编辑器自带的内容插入API,绕过自动段落包裹逻辑,示例代码:
// 获取当前表单中test_field字段对应的编辑器实例 const editorInstance = this.record.widgets.test_field.editor; // 构造要插入的带指定值的表格行 const insertRowHtml = ` <tr> <td style="border: 1px solid #e0e0e0; padding: 6px 8px;">前端动态插入的指定值</td> </tr> `; // 调用编辑器内置的插入HTML命令写入内容 editorInstance.execCommand('insertHTML', false, insertRowHtml);
常见踩坑提醒
- 不要在XML的field配置中额外开启
sanitize="1"属性,会触发默认的严格标签过滤,把所有表格结构全部过滤为纯文本。 - 如果你需要在已有的表格内容后面追加行,不要重新拼接整个表格覆盖原有内容,优先调用编辑器的插入命令在对应位置插入行结构即可。
内容的提问来源于stack exchange,提问作者Kirill Kriachenko
相关产品推荐
相关产品推荐

