Search code examples
pythonxmlpython-2.7odoo-8odoo

How to set this specific domain on OpenERP/Odoo?


I have the next table in Odoo, named relationship, which comes from the relation between the table girl and the table boy:

| girl_id | boy_id | relationship_type |

| 1 | 2 | friends |

| 1 | 3 | siblings |

| 2 | 7 | lovers |

So:

  • In the table girl there's a field relationships which is a one2many pointing to the table relationship.
  • In the table boy there's a field relationships which is a one2many pointing to the table relationship.
  • In the table relationship there are two fields, girl_id and boy_id, both pointing to the tables girl and boy respectively.

Scenario:

In the forms of girl and boy there's the field relationships. When I add a new relationship for a girl or a boy, a form is opened to fill in the fields of the table relationship (girl_id, boy_id and relationship_type). Imagine I'm in the form of a girl, I click on add a new relationship and the form is opened. I implemented this in order not to see the girl_id (it's invisible but it contains the ID of the current girl). So I can see only two fields (boy_id and relationship_type).

What I want:

Keeping on with the example, if I open the dropdown of boy_id, I'll see all boys, even the ones who are already related to this girl. For example, if I'm adding a relationship to the girl with id 1, I must not see boys with ids 2 and 3, if the girl is the one with id 2, I must not see the boy with id 7.

My attempt

I've created two fields in the table relationships, named boys_of_the_girl (one2many related to 'girl_id.relationships') and girls_of_the_boy (one2many related to 'boy_id.relationships').

My code: (Example: creating a relationship for a girl)

<field name="girl_id" invisible="1"/>
<field name="boys_of_the_girl" invisible="1"/>
<field name="boy_id" domain="[('id', 'not in', boys_of_the_girl)]"/>
<field name="relationship_type"/>

The error:

RuntimeError: maximum recursion depth exceeded while calling a Python object

Can anyone help me, please? Thank you!

EDIT

Table boy

relationships = fields.One2many(comodel_name='relationship',
                                inverse_name='boy_id',
                                string='Relationships')

Table girl

relationships = fields.One2many(comodel_name='relationship', inverse_name='girl_id', string='Relationships')

Table relationship

boy_id = fields.Many2one(comodel_name='boy', string='Boy', required=True)
girl_id = fields.Many2one(comodel_name='girl', string='Girl', required=True)
relationship_type = fields.Char(string='Relationship type')

Solution

  • Well, finally I found out that it's not possible to manage this through XML code, but it's possible to achieve the same purpose through Python:

    Only with this function (and another one similar for the domain of girl_id in the other form):

    @api.onchange('girl_id')
    def on_change_girl_id(self):
        current_girl_id = self.env.context.get('default_girl_id', False)
        relationship_recordset = self.search([('girl_id', '=', current_girl_id)])
        boy_recordset = relationship_recordset.mapped('boy_id')
        boy_ids = boy_recordset.mapped('id')
        boy_id_domain = [
            ('id', 'not in', boy_ids)
        ]
        result = {
            'domain': {
                'boy_id': boy_id_domain,
            },
        }
        return result
    

    And this way it's not necessary to add any domain to the field boy_id in the XML form. This function will affect the form where you set a relationship for a girl, as I wrote above, another similar function must be declared to manage the right behaviour when setting a relationship for a boy.