如何动态遍历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
相关产品推荐
相关产品推荐

