SlyK
SlyK

Reputation: 185

How to create a recursive function in Python to create a dict which maps Odoo 8 relational field records?


I am trying to create a Python function that maps nodes of a web created by Odoo relational fields, and returns such map as a dictionary.
I'll try to explain.

Let us consider the model 'account.account', and its fields 'child_parent_ids' (o2m to same class) and 'parent_id' (m2o to same class, inverse of previous field).
How can I create a dictionary where every key is a record of 'account.account', and every key's values are dictionaries made of their children records recursively, or 'True' if such record has no child records?

E.g., let us consider this web:

account
      |
      |_child-1
      |
      |_child-2
      |       |
      |       |_child-21
      |       |_child-22
      |       |_child-23
      |
      |_child-3
      |       |
      |       |_child-31
      |       |_child-32
      |       |        |
      |       |        |_child-321
      |       |        |_child-322
      |       |        |_child-323
      |       |        |_child-324
      |       |
      |       |_child-33
      |       
      |_child-4


The function I'm looking for should return a dictionary like this:

{'account':
    {'child-1': True},
    {'child-2': 
        {'child-21': True},
        {'child-22': True},
        {'child-23': True},
     },
    {'child-3':
        {'child-31': True},
        {'child-32':
            {'child-321': True},
            {'child-322': True},
            {'child-323': True},
            {'child-324': True}
         },
        {'child-33': True},
     }
    {'child-4': True},
 }


I tried to create a recursive function as follows:

@api.multi
def get_tree_dict(self):
    tree_dict = {}
    if self.child_parent_ids:
        for child in child_parent_ids:
            tree_dict[self] = child.get_tree_dict()
        return tree_dict
    else:
        tree_dict[self] = True
        return tree_dict


It doesn't seem to work (it doesn't return the expected output, dictionary stops at first True value), and I can't find out why (please don't be too hard on me).
Can please anyone help me, by showing the error I'm making and how can I solve it?
Please note that the depth of the dictionary is not known a priori, so I think the method should be recursive (or iterative).

Upvotes: 1

Views: 1643

Answers (1)

englealuze
englealuze

Reputation: 1663

Because for dictionary, 1 key can have only 1 value. You can not have multiple children assigned to 1 parent key.

Your code here

for child in child_parent_ids:
    tree_dict[self] = child.get_tree_dict()

will overwrite the previous child from the same parent. At the end you have 1 parent key only one child.

May be you could consider to use lists to help to form the tree structure, instead of only dictionaries. Then you can append to the list as many children as you have.

Something like (since no minimal working example, don't know how exactly your code work, not guarantee work, consider it just as an idea):

expected_dict = 
{'account':
  [
    {'child-1': True},
    {'child-2': [{'child-21': True}, {'child-22': True}, {'child-23': True}]},
    {'child-3': [{'child-31': True}, {'child-32':[{'child-321': True}, {'child-322': True}]},
    {'child-4': True}
  ]
}

def get_tree_dict(self):
    tree_dict = {}
    if self.child_parent_ids:
        tree_dict[self] = []
        for child in child_parent_ids:
            tree_dict[self].append(child.get_tree_dict())
        return tree_dict
    else:
        tree_dict[self] = True
        return tree_dict

Upvotes: 1

Related Questions