第三章 字段类型

篇别:第一篇 基础知识

本章学习目标

  • 能按场景选择 标量 / 关系 / 计算 字段类型。
  • 能正确配置 Monetary、Selection、Many2many 等易错字段。
  • 理解 Odoo 19 关系字段命名 规范对升级的影响。

3.1 基础字段

3.1.1 知识要点

类型 注意点
Char 长文本请用 Text;注意翻译与 trim
Html XSS:展示用户 HTML 需消毒策略
Float digits=(16,2) 等精度
Monetary 必须 currency_field
Date / Datetime 存储 UTC,界面按用户时区
Binary 附件大文件考虑 attachment=True
Selection 静态列表或 callable 动态选项

3.1.2 案例

案例 A:金额 + 币种

currency_id = fields.Many2one('res.currency', default=lambda self: self.env.company.currency_id)
price = fields.Monetary(currency_field='currency_id')

案例 B:动态 Selection

def _selection_state(self):
    return [('draft', '草稿'), ('done', '完成')]

state = fields.Selection(selection=_selection_state, default='draft')

3.1.3 截图占位

图 3-1 表单中 Monetary 与币种字段联动显示

3.1.4 本节练习

  1. 判断Monetary 可以不指定 currency_field。( )
  2. 实操:为某模型增加 Html 字段并在表单用 widget="html" 展示(若版本支持)。

参考答案提示:1. 错。


3.2 关系字段

3.2.1 知识要点

  • Many2oneondeletecascade/set null/restrict)必须考虑业务。
  • One2many:仅用于子表编辑,不可搜索为主域(通常)。
  • Many2many:可自定义 relationcolumn1column2
  • Reference:多态,维护成本高,慎用。

3.2.2 案例

案例:标签多对多

tag_ids = fields.Many2many(
    'library.tag',
    'library_book_tag_rel',
    'book_id', 'tag_id',
    string='标签',
)

3.2.3 截图占位

图 3-2 技术菜单中某 Many2many 的中间表关系

3.2.4 本节练习

  1. 简答:删除主记录时希望子明细一并删除,ondelete 应设为什么?
  2. 实操:新建 library.tag 并与 library.book 建立 Many2many

参考答案提示:1. 子表 Many2one 上 ondelete='cascade'


3.3 计算字段与依赖

3.3.1 知识要点

  • @api.depends 必须覆盖所有读取的字段路径。
  • store=True:可搜索、可索引;注意依赖变化时的 重算成本
  • inverse:实现可写计算字段。

3.3.2 案例

案例:可写 display_name

display_name = fields.Char(compute='_compute_display_name', inverse='_inverse_display_name', store=True)

@api.depends('code', 'name')
def _compute_display_name(self):
    for rec in self:
        rec.display_name = f'[{rec.code}] {rec.name}'

3.3.3 截图占位

图 3-3 开发者模式「查看字段依赖」或日志中 depends 调试

3.3.4 本节练习

  1. 改错@api.depends('line_ids') 但 compute 里用了 line_ids.price,会有什么问题?
  2. 实操:为图书增加 line_count = fields.Integer(compute=...) 统计关联借阅行数。

参考答案提示:1. 子字段变化不会触发重算,应 @api.depends('line_ids.price')


3.4 字段属性

3.4.1 知识要点

stringhelpdefaultrequiredreadonlycopygroupscompany_dependenttracking 等。

安全groups 仅 UI 层辅助,须 ACL。

3.4.2 案例

secret_note = fields.Text(groups='base.group_system', copy=False)

3.4.3 截图占位

图 3-4 以普通用户登录,确认 groups 字段不可见

3.4.4 本节练习

  1. 简答copy=False 的典型使用场景?
  2. 实操:某字段仅「经理组」可编辑,写出 groups 与 ACL 配合思路。

参考答案提示:1. 序列号、临时令牌等复制时不应带上。


3.5 命名标准化(新增)

3.5.1 知识要点

关系字段统一 _id / _ids(如 product_uom_id)。升级时用 upgrade_code 与 Changelog 对照自定义代码。

3.5.2 案例

案例:重命名自定义字段

  • Python:old_refpartner_ref_id
  • 同步修改:视图 XML、报表 QWeb、外部 API 脚本。

3.5.3 截图占位

图 3-5 IDE 全局搜索旧字段名的结果列表

3.5.4 本节练习

  1. 列举:你项目中三个应带 _id 后缀但仍未统一的字段名(若有),并规划重命名步骤。

本章综合练习

  1. 设计:library.loanbook_iduser_id(借阅人)、planned_return_date,全部加上合理 ondelete/required
  2. 思考题:何时用 related 代替重复 compute

本章对应白皮书目录:第三章 字段类型。