Odoo - Iterate through field, take the values and put them in a new field

1.4k Views Asked by At

Hay I am new to Odoo Customizing and Python and wanted to know how I can iterate through a field and take the values out of the field and put them in a new one.

The field I want to iterate through contains multiple email adresses. I want to iterate through these email adress fields, collect the email adresses and store them together in a new field.

For that I need a function.

The field I want to iterate through: My One2many field contains multiple mail adresses which I want to iterate through and collect.


field_contacts_customer_info = fields.One2many(
        'contacts.customer.information', 'another_id', string='Contacts for customer information')

The field I want to store the collected email adresses in:

selected_email = fields.Char(compute='compute_email')

This is my class: I want to collect all the email adresses from the mail_contacts field.

    _name = 'contacts.customer.information'
    _rec_name = 'name_contacts'

    name_contacts = fields.Many2one(
        'res.partner', string="Person", domain = [('is_company', '=', False)])

    mail_contacts = fields.Char(
        related = 'name_contacts.email' ,string="Email")

    another_id = fields.Many2one('res.partner', string="AnotherID")

My Try: This function collects only the last set record of the field_contacts_customer_info field and puts this record in the selected_email field of every company.So it does not work right. It should collect all the mails of the field_contacts_customer_info field for every company seperated and then put them in the selected_mail field of the belonging company.

@api.onchange('field_contacts_customer_info.mail_contacts')
def compute_email(self): 
        list_email = [] 
        for record in self: 
            if record.is_company: 
                for element in record.field_contacts_customer_info: 
                    if element.name_contacts: 
                        list_email.append(element.mail_contacts) 
                    for email in list_email: 
                        self.selected_email = email 

Thanks.

1

There are 1 best solutions below

17
Kenly On

You need to iterate over self which is a record set and loop over field_contacts_customer_info field to get mail_contacts field values.

@api.depends('field_contacts_customer_info.mail_contacts')
def get_email(self):
    for record in self:
        record.selected_email = ','.join(info.mail_contacts for info in record.field_contacts_customer_info if info.mail_contacts)

Then set the compute attribute to get_email:

selected_email = fields.Char(string="Mail4Info", compute='get_email')

You can check the ORM documentation on how to use the computed fields.

Edit (compute method):

You are setting the value of selected_email to each element of list_email, after the compute_email is executed the value of selected_email will always be the last value of list_email.

The last for loop is executed each time we loop over record.field_contacts_customer_info, it should be at the same level as the second loop.

The list_email is declared before we loop over records (it is not reset in the loop), after the first record, each record will use the email values of previous records.

When record.is_company is evaluated to False, the compute method will not assign a field value, you should see the following error:

ValueError: Compute method failed to assign {record description}.selected_email

It happens because the compute method must assign a field value

Example:

@api.depends('field_contacts_customer_info.mail_contacts')
def compute_email(self):
    for record in self:
        list_email = []
        if record.is_company:
            for element in record.field_contacts_customer_info:
                if element.name_contacts:
                    list_email.append(element.mail_contacts)
            emails = ""
            for email in list_email:
                emails += email + " "
            record.selected_email = emails
        else:
            record.selected_email = ""

You can change the list_email type to a string and avoid looping again to get the field value:

Example:

@api.depends('field_contacts_customer_info.mail_contacts')
def compute_email(self):
    for record in self:
        list_email = ""
        if record.is_company:
            for element in record.field_contacts_customer_info:
                if element.name_contacts:
                    list_email += element.mail_contacts
        record.selected_email = list_email