You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何动态遍历Odoo模型记录集字段值以生成CSV报告

Odoo动态获取继承模型字段并生成CSV报告的问题

我正在基于继承的模型生成CSV报告,需要动态获取模型的字段名作为CSV表头,同时提取每条记录的对应字段值。由于子模型可能新增字段,不能硬编码字段名。

目前我通过fields_get()获取字段名:

class MyClass(models.Model):
    _inherit = 'custom.model'

    def csv_export(self):
        headings = self.fields_get()
        header = list(headings.keys())
        print(header)
        # 输出示例: ['field1', 'field2', ...]

通过搜索获取记录集:

records = self.env['custom.model'].search([('country', '=', 'US')], limit=n)

遍历记录集时,硬编码字段名(如rec_val.state)可以正常获取值,但尝试用rec_val[header[index]]或rec_val.header[index]动态访问时均报错。用search_read()返回的字典列表也无法正确匹配表头字段,同时我需要排除部分不需要的字段,求正确的动态访问方案。


1. 正确的动态访问记录字段值方式

Odoo的模型记录对象是类实例,动态访问字段值推荐使用Python内置的getattr()函数,这是最可靠的方式:

# 遍历记录集生成行数据
for rec in records:
    row = []
    for field_name in header:
        # 获取字段值
        value = getattr(rec, field_name)
        # 处理关联字段(如many2one/many2many)的显示需求
        field_type = self.fields_get([field_name])[field_name]['type']
        if field_type == 'many2one':
            # 取关联记录的显示名称,为空则返回空字符串
            value = value.display_name if value else ''
        elif field_type in ['many2many', 'one2many']:
            # 多关联字段拼接显示名称
            value = ', '.join([item.display_name for item in value])
        row.append(value)
    # 将row写入CSV

如果一定要用下标访问,确保直接传入字段名字符串:rec[field_name](注意不要写成嵌套索引rec[header[index]]的错误形式),但getattr()兼容性更好。

2. 过滤不需要的字段

在生成表头阶段就排除不需要的字段,避免后续处理麻烦:

# 定义需要排除的字段列表(比如系统字段、内部字段)
EXCLUDE_FIELDS = ['create_uid', 'write_uid', 'create_date', 'write_date', '__last_update']

def csv_export(self):
    headings = self.fields_get()
    # 过滤掉不需要的字段
    header = [field for field in headings.keys() if field not in EXCLUDE_FIELDS]
    # 后续逻辑...

3. 使用search_read简化处理

如果不需要记录对象的其他方法,直接用search_read()并指定fields参数,返回的字典可以直接通过键名访问值,同时自动过滤未指定字段:

def csv_export(self):
    EXCLUDE_FIELDS = ['create_uid', 'write_uid', 'create_date', 'write_date']
    # 获取过滤后的字段列表
    available_fields = [f for f in self.fields_get().keys() if f not in EXCLUDE_FIELDS]
    # search_read直接返回包含指定字段的字典列表
    records_data = self.env['custom.model'].search_read(
        [('country', '=', 'US')],
        fields=available_fields,
        limit=n
    )
    # 遍历生成CSV行
    for data in records_data:
        row = []
        for field_name in available_fields:
            value = data[field_name]
            # 处理关联字段:search_read返回many2one为(id, name)元组
            if isinstance(value, tuple):
                value = value[1]
            # 处理多关联字段返回的id列表(如需显示名称需额外查询)
            elif isinstance(value, list) and field_name in self.fields_get() and self.fields_get()[field_name]['type'] in ['many2many', 'one2many']:
                records = self.env[self.fields_get()[field_name]['relation']].browse([item[0] for item in value])
                value = ', '.join([rec.display_name for rec in records])
            row.append(value)
        # 将row写入CSV

内容的提问来源于stack exchange,提问作者jnkrois

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:02:44