很多 Odoo 初学者会把 display_name 理解成“给界面显示的一列文字”。这不算错,但远远不够。
在官方 ORM 里,display_name 其实是一个很核心的接口层概念。它不只是决定“看起来显示什么”,还会影响:
- 关系字段下拉里怎么展示
name_search()怎么搜name_create()如何快速创建- 没配置
_rec_name时系统怎样兜底
所以它不是简单 UI 字段,而是 对象对外可识别名称的统一协议。
一、display_name 默认怎么来
在 /home/ubuntu/odoo-temp/odoo/orm/models.py 里,_compute_display_name() 的逻辑很清楚:
- 如果模型定义了
_rec_name - 就把
_rec_name对应字段转换成显示值 - 否则退回成
model_name,id
这说明一件事:
display_name的默认中心,不是固定叫name的字段,而是_rec_name。
所以很多模型虽然没有直接拿 name 做显示,但只要 _rec_name 指向别的字段,界面上看到的显示名就会跟着变。
二、为什么搜索显示名时,不是直接搜 display_name 列
另一个很关键的方法是 _search_display_name()。
它不是去数据库里找一个真实叫 display_name 的列,而是根据:
_rec_names_search- 或
_rec_name
把“搜索显示名”翻译成真正的 domain。
默认逻辑会:
- 对普通字段按 operator 生成搜索条件
- 对关系字段继续搜关联对象的
display_name - 对不同操作符尝试做类型转换
这意味着 display_name 搜索并不是一个简单的“搜文本列”,而是一个 由 ORM 动态翻译的搜索语义。
也正因为这样,不同模型完全可以重写它,改成更符合业务直觉的搜索行为。
三、name_search() 其实只是上层入口,不是搜索逻辑本体
源码里 name_search() 很值得看,因为它没有自己搞一套复杂搜索,而是:
- 构造
Domain('display_name', operator, name) - 再叠加额外 domain
- 调
search_fetch(..., ['display_name']) - 返回
(id, display_name)列表
这告诉我们:
name_search()是一个关系字段候选入口- 真正的搜索语义落在
_search_display_name() - 真正的展示值又落回
display_name
也就是说,显示和搜索看似两件事,其实被同一套协议串了起来。
四、name_create() 为什么看起来简单,却很依赖 _rec_name
name_create() 的默认实现更简单:
- 如果有
_rec_name - 就直接
create({self._rec_name: name}) - 然后返回
(id, display_name) - 如果没有
_rec_name,就只能警告并返回失败值
这说明快速创建并不是“随便创建一个对象”,它默认假设:
- 这个模型存在一个适合作为快速输入主标识的字段
_rec_name就是那个入口
所以有些模型能在 many2one 下拉里顺滑“边输边建”,有些模型就不适合,根本原因不在前端,而在模型命名协议本身。
五、为什么很多模型会重写这套逻辑
官方的 res.partner 就不是完全照搬默认行为。它通过 _rec_names_search 把:
complete_nameemailrefvatcompany_registry
都纳入候选搜索字段。
这很合理,因为联系人在真实业务里,用户想用来找人的关键词从来不止名字。
这也说明一个实战原则:
- 如果你的模型“显示用主名”很简单,默认
_rec_name足够 - 如果用户真实搜索习惯很多样,就该认真设计
_search_display_name()或_rec_names_search
六、新手最容易混淆的几个点
1)“display_name 就是数据库里的 name 列”
不是。它默认依赖 _rec_name,甚至可能完全由自定义计算逻辑决定。
2)“name_search 自己决定怎么搜”
不完全对。它更多是入口封装,真正翻译搜索条件的是 _search_display_name()。
3)“name_create 就是所有模型都能用的快速创建”
也不是。没有合适 _rec_name 的模型,默认并不适合这样建。
七、实战里怎么设计更稳
如果你在做自定义模型,可以先问自己三个问题:
- 用户看到这条记录时,最自然的名称是什么?
- 用户搜它时,会用哪些关键词?
- 这个模型适不适合只靠一个文本值快速创建?
这三个问题分别对应:
display_name/_rec_name_search_display_name/_rec_names_searchname_create
想清楚它们,many2one 体验通常会顺很多。
结语
display_name 真正重要的地方,不是“界面显示哪串字”,而是它把 显示、搜索、快速创建 三件事串成了一套统一命名协议。
理解这套边界后,你会发现很多关系字段体验好不好,并不主要取决于前端,而取决于模型层有没有把“对象该如何被人识别”设计明白。
DISCUSSION
评论区