如何在 Python 中使用多级词典创建 Odoo 记录

How to create Odoo records with multilevel dictionaries in Python

我正在努力创建一种递归方法来在 Odoo 中自动创建记录。 我请求 SOAP 服务的 WSDL 并对其进行处理,直到收到以下字符串:

{'notificaCertificadoRevocado':{
   'input': {
      'SolicitudNotificaRevocado':{
         'optional': False,
         'type': {
            'certificado': {
                'optional': False,
                'type': 'String(value)'
                },
            'codigoAmbiente': {
                'optional': False,
                'type': 'Int(value)'
                }
             }
          }
       }
   }
}

此词典有 1 个父参数“SolicitudNotificaRevocado”和 2 个子参数“certificado”和“codigoAmbiente”。

目前我的 python 方法如下所示:

    def _prepare_parameter_list(self, parameter_dict, recursive_data=False):
        building_data = recursive_data if recursive_data else {}
        parameter_list = []
        for key, value in parameter_dict.items():
            if key != 'optional' and key != 'type':
                # Create parameters
                parameter_name_dict = {
                    'name': key,
                    'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
                }
                characterization_dict = self._prepare_parameter_list(value)
                built_parameter_dict = {**parameter_name_dict, **characterization_dict}
                parameter_list.append((0, 0, built_parameter_dict))
                # TODO: Here the code stops
                return parameter_list
            else:
                if key == 'optional':
                    building_data = {**building_data, **{'optional': value}}
                if key == 'type':
                    if isinstance(value, dict):
                        building_data = {**building_data, **{'parameter_ids': self._prepare_parameter_list(value)}}
                    else:
                        building_data = {**building_data, **{'type': value.split('(')[0]}}
        return building_data

这工作很好,只有一个问题,正在 returned 的数据具有以下形式:

[(0, 0, {
   'name': 'SolicitudOperacionesCuis',
   'description': 'Solicitud Operaciones Cuis',
   'optional': False,
   'parameter_ids': [
      (0, 0, {
         'name': 'codigoAmbiente',
         'description': 'Codigo Ambiente',
         'optional': False,
         'type': 'Int'})]
      })
      ]

问题是处理其中一个子参数后的方法因“return parameter_list”部分而停止。 (我什至在问题部分添加了 TODO 注释) 我想检索以下数据:

[(0, 0, {
   'name': 'SolicitudOperacionesCuis',
   'description': 'Solicitud Operaciones Cuis',
   'optional': False,
   'parameter_ids': [
      (0, 0, {
         'name': 'certificado',
         'description': 'Certificado',
         'optional': False,
         'type': 'String'})]
      }),
      (0, 0, {
         'name': 'codigoAmbiente',
         'description': 'Codigo Ambiente',
         'optional': False,
         'type': 'Int'})]
      })
       ]

我应该如何调整我的方法来实现这个目标? 使用递归方法很难!

最后我采取了另一种方法,彻底重构了该方法。 因为我之前的代码还有一个问题。如果检查之前的期望输出:

[(0, 0, {
   'name': 'SolicitudOperacionesCuis',
   'description': 'Solicitud Operaciones Cuis',
   'optional': False,
   'parameter_ids': [
      (0, 0, {
         'name': 'certificado',
         'description': 'Certificado',
         'optional': False,
         'type': 'String'})]
      }),
      (0, 0, {
         'name': 'codigoAmbiente',
         'description': 'Codigo Ambiente',
         'optional': False,
         'type': 'Int'})]
      })
       ]

存在 Odoo 无法识别的嵌套 One2many 记录创建。 无论如何,由于我无法使以前的代码起作用,所以我开始单独创建记录:

    def _create_parameters(self, process_object, parameter_id=False, parent_parameter_id=False):
        for key, value in process_object.items():
            if key != 'optional' and key != 'type':
                try:
                    soap_parameter = self.env['soap.parameter'].search([
                        '&', '&', '&', '&',
                        ['active', '=', True],
                        ['name', '=', key],
                        ['description', '=', ' '.join(word.capitalize() for word in camel_case_split(key))],
                        ['method_id', '=', self.id],
                        ['parent_id', '=', parent_parameter_id]
                    ], limit=1)[0]
                except IndexError:
                    # Create parameters
                    soap_parameter = self.env['soap.parameter'].create({
                        'name': key,
                        'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
                        'method_id': self.id,
                        'parent_id': parent_parameter_id
                    })
                self._create_parameters(value, soap_parameter, soap_parameter.id)
            if parameter_id:
                if key == 'optional':
                    parameter_id.write({'optional': value})
                if key == 'type':
                    if isinstance(value, dict):
                        self._create_parameters(value, parent_parameter_id=parent_parameter_id)
                    else:
                        value_type = value.split('(')[0]
                        if value_type == 'Int':
                            value_type = 'int'
                        elif value_type == 'String':
                            value_type = 'str'
                        elif value_type == 'Long':
                            value_type = 'float'
                        parameter_id.write({'type': value_type})

此代码将搜索和更新或创建我的参数。

如果输入数据是已知的,而且似乎有用的数据是输入字典中的数据,则不需要递归元素。 更新了下面输出您预期输出的类似函数

def _prepare_parameter_list(parameter_dict):
    def _return_data_type(value_type):
        if value_type == 'Int':
            value_type = 'int'
        elif value_type == 'String':
            value_type = 'str'
        elif value_type == 'Long':
            value_type = 'float'
        return value_type

    parent = parameter_dict.get('notificaCertificadoRevocado')
    building_data = []
    if parent and parent.get('input'):
        for key, value in parent['input']:
            vals = {
                'name': key,
                'description': ' '.join(word.capitalize() for word in camel_case_split(key)),
                'optional': value.get('optional'),
            }
            parameter_ids = []
            if value.get('type'):
                for par_key, par_value in value['type']:
                    pams = {
                        'name': par_key,
                        'description': par_key.capitalize(),
                        'optional': par_value.get('optional'),
                        'type': par_value.get('type') and _return_data_type(par_value['type'].split('(')[0]) or False,
                    }
                    parameter_ids.append((0, 0, pams))
            vals.update(parameter_ids=parameter_ids)
            building_data.append((0, 0, vals))
    return building_data