DEV Community

Guewen Baconnier
Guewen Baconnier

Posted on • Edited on

2

Using a domain stored in a field for a Many2one

It is a very common pattern in Odoo to filter available records in a Many2one depending on another field.

For instance, users can select a Stock Location only if it abides by some rules. You may have a computed field, that gives the allowed locations for a move line.

The issue

Let's take a fictive use case where we allow moving a product in a location only if this location is associated to this product.

In Python:




class StockMoveLine(models.Model):
    _inherit = "stock.move.line"

    allowed_location_ids = fields.Many2many(
        comodel_name="stock.location",
        compute="_compute_allowed_location_ids"
    )

    @api.depends("product_id", "move_id.location_dest_id")
    def _compute_allowed_location_ids(self):
        for line in self:
            destination = line.move_id.location_dest_id
            line.allowed_location_ids = destination.allowed_sublocations(line.product_id)



Enter fullscreen mode Exit fullscreen mode

And in the XML view:



<field name="allowed_location_ids" invisible="1" />
<field name="location_dest_id" domain="[('id', 'in', allowed_location_ids)]"/>


Enter fullscreen mode Exit fullscreen mode

It works quite well, until you have a large number of locations, e.g. 5000 allowed locations. When you change the product, an onchange is triggered to get the new allowed_location_ids, which is done very fast server_side, but the front-end starts to freeze (5-10 seconds).

Image of browser freezing with

This issue happens because we return 5000 ids to a Many2many widget, which has to process every single id.

ℹ️ I encountered this issue in Odoo 13.0, it may or may not still happen on newer versions.

The solution

Here comes to the rescue the OCA module web_domain_field.

As stated in its description:

In order to mitigate these limitations this new addon allows you to use the value of a field as domain of another field in the xml definition of your view.

Go read the description of the module as it gives other interesting use cases.

Using a domain set directly in the field short-circuits the Many2many widget on the view and fixes the performance issue.

Our code would now look like:

In Python:




class StockMoveLine(models.Model):
    _inherit = "stock.move.line"

    allowed_location_domain = fields.Char(
        compute="_compute_allowed_location_domain"
    )

    @api.depends("product_id", "move_id.location_dest_id")
    def _compute_allowed_location_domain(self):
        for line in self:
            destination = line.move_id.location_dest_id
            allowed_locations = destination.allowed_sublocations(line.product_id)
            line.allowed_location_domain = json.dumps([("id", "in", allowed_locations.ids)])



Enter fullscreen mode Exit fullscreen mode

And in the XML view:



<field name="allowed_location_domain" invisible="1" />
<field name="location_dest_id" domain="allowed_location_domain"/>


Enter fullscreen mode Exit fullscreen mode

The real use case used to showcase this Odoo module was in stock_storage_type.

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

While many AI coding tools operate as simple command-response systems, Qodo Gen 1.0 represents the next generation: autonomous, multi-step problem-solving agents that work alongside you.

Read full post

Top comments (2)

Collapse
 
martinvarela85 profile image
Martin Varela

Great addon! Solved us a lot of performance issues.

The domain field shouldn't be fields.Char?

Collapse
 
guewen profile image
Guewen Baconnier

Oh, yes of course! Thanks for the correction :)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay