数据的准备

odoo 作为一个数据驱动的开发框架,我们首先需要做的就是原始数据的预处理,这里就是省市县数据的准备工作。

odoo 可以通过 DataFiles 在模块安装的时候进行相关数据的初始化,所以我们首先要想办法生成我们所需的 DataFiles 文件。

在翻阅系统自带模块的时候,我发现在 中国会计科目表 中已经将中国的省份信息添加进入了系统,基于 DRY原则,我们可以直接利用其中的数据。

接下来的问题就是如何根据已有的省份信息 连同市县信息生成关联数据,并将其存储进入 odoo 系统。我们第一个想到的就是直接更新数据库,但是由于 odoo 本身会在自己系统内部维护一套模型数据,所以不推荐直接进行数据库原生操作,最好的选择是使用 odoo DataFiles

根据相关文档,我们设计如下的xml结构:

<record id="{city_id}" model="res.country.city">
<!--city_id格式定为state_{省名拼音首字母}_city_{市拼音首字母}-->
<field name="name">{city_name}</field>
<field name="state_id" ref="l10n_cn.state_HE"/>
<!--此处ref指向系统中已经存在的省份信息-->
</record>
<record id="{district_id}" model="res.country.district">
<!--district_id格式定为city_{所属城市拼音首字母}_{区县拼音首字母}-->
<field name="name">东城区</field>
<field name="city_id" ref="china_address.state_bjs_city_sxq"/>
<!--此处ref指向城市信息中的id-->
</record>

数据结构定义好了,接下来的问题就是如何生成数据了,这里我写了一个脚本来生成我们需要的数据文件:

这里使用到的原始数据可以直接访问 gist

业务逻辑

三级联动的业务逻辑其实很简单,无外乎就是监听第一级然后更新第二级列表,以此类推。

与一般我们直接在前端页面编写逻辑不同,在 odoo 中我们就必须得利用 onchange 来实现。

这里我们可以利用 domain 来过滤联动的数据,比如当我选择江苏省的时候,城市下拉列表应该只过滤出所属于江苏省的城市数据。

部分逻辑代码如下:

@api.onchange('state_id')
def _onchange_state_id(self):
self.city_id = None
self.district_id = None
if self.state_id:
return {'domain': {'city_id': [('state_id', '=', self.state_id.id)]}}
else:
return {'domain': {'city_id': []}}

视图