Odoo fields computed for too many records - odoo

I have some data in a tree structure. One of the fields are computed (not stored) using data from the children.
In a form view, I show the computed field and the parent field.
Because of this, I end up reading many records from the model - and Odoo seems to compute the computed field for all of these records, even though the view only needs the computed field for one record.
I thought this was caused by the prefetch mechanism, but I tried to set prefetch_fields=False in the context, and that didn't help.
Any idea how I can avoid computing all the unnecessary values? (Storing the computed field is not an option).
A quick example to give an idea of the construction:
parent_id = fields.Many2one(...)
child_ids = fields.One2many(...) # Inverse parent relation
comp = fields.Integer(compute="_compute_comp")
#api.one
def _compute_comp(self):
sum = 0
for c in self.child_ids:
sum += c._get_complicated_value()
self.comp = sum
and a view with:
<field name="parent_id" />
<field name="comp" />
comp is always computed for the children's children. With <field name="parent_id" /> it is also computed for ALL the parent's children.

you can use #api.depends
#api.depends
This decorator will trigger the call to the decorated function if any of the fields specified in the decorator is altered by ORM or changed in the form:
#api.depends('name', 'an_other_field')
def afun(self):
pass
Note:
when you redefine depends you have to redefine all #api.depends, so it
loses some of his interest.
One of the great improvement of the new API is that the depends are automatically inserted into the form for you in a simple way. You do not have to worry about modifying views anymore.
#api.one
#api.depends('child_ids')
def _compute_comp(self):
sum = 0
for c in self.child_ids:
sum += c._get_complicated_value()
self.comp = sum

Related

How do I create a complete record with inheritance type delegation?

example/models/example.py
class Example(models.Model)
_name = 'example.model'
product_tmpl_id = fields.Many2one('product.template','Product Template',delegate=True,ondelete='cascade',required=True)
example/models/product_template.py
class ProductTemplate(models.Model)
_inherit='product.template
example_ids = fields.One2many('example.model','product_tmpl_id',string='Item')
example/views/example.xml
<form>
<field name="product_tmpl_id" widget="many2one"/>
</form>
My understanding was that a product_template record would be automatically created with example, but this field is required and not letting me save a new record. When I perform an import of the example data adding these columns at the beginning for product_template ("exampleNN", "name", "type", "categ_id/id", "sale_ok", "purchase_ok",...) I get a matching product template with an id of "exampleNN_product_template" and identical name (though example does not have name so it must be using product template).
product_tmpl_id does not like being on the form view as it is required, yet not created yet with delegation inheritance. I used tree view instead to see product_tmpl_id. I was curious about its value after doing an import.

Selection Filtering By Another Selection

I'm looking for a way to filter subsequent selections depending on which ones of them are filled.
I want to have a tree-like structure for setting locations as such:
=>Country
==>State
===> District
So say you enter the district first, you'd only have one choice in the other two.
Say you enter the country first, you'd have a more limited selection of the latter two.
I know i should be going with many2one fields but all i can get working at this point is multiple selections that turn visible/invisible which is highly inefficient.
I'm fairly new to Odoo and am finding the docs somewhat lacking. Any help would be appreciated!
I would play around with many2one fields and domains using the operator =?
For example:
class MyModel(models.Model):
_name = "my.model"
country_id = fields.Many2one(comodel_name="res.country")
state_id = fields.Many2one(comodel_name="res.country.state")
disctrict_id = fields.Many2one(comodel_name="res.country.state.district")
I don't know if the model names are correct, but you should already know them.
And in the view use the domain with the mentioned operator:
<field name="country_id"
domain="[('state_ids', '=?', state_id),('state_ids.district_ids', '=?', district_id)]" />
<field name="state_id"
domain="[('country_id', '=?', country_id),('district_ids', '=?', district_id)]" />
<field name="disctrict_id"
domain="[('state_id', '=?', state_id),('state_ids.country_id', '=?', country_id)]" />
I didn't make any tests on those AND conditions/domains. And i don't know the structure of those 3 models. My assumption is, that there is a one2many or many2many relation on res.country -> res.country.state and res.country.state -> res.country.state.district.

odoo 9 how to inherit many2one field value from parent view

I have hospital appointment registration model that is relates to lab test model :
'lab_test_ids': fields.one2many('oeh.medical.lab.test','apoointment','Lab Tests', readonly=False,states={'Completed': [('readonly', True)]}),
in the view I have a TAB (page) under appointment form :
page string="Lab Tests"> <field name="lab_test_ids" context="{'default_appointment': active_id}" domain="[('appointment', '=', active_id)">
My challenge is that I have patient and physician in both views (selection fields) that relate to two other models. I was wondering if I could SET value for a patient field in the parent view and inherit that value to the child view (Lab test). how can I do that?
NOW i use domain to filter through the patient. and the candidate patient is Only one . how can I set this value to the field automatically.
> <field name="patient" domain="[('id', '=', parent.patient)]"
I appreciate your help.
I'm not sure I 100% fully understand the question but you only have a few options to handle the scenario of copying field data between views.
1.
Onchange Field. Create an onchange if they are on the same view. (Don't believe this will work for you.)
lab_test = fields.One2many(...)
#api.onchange('lab_test')
def _onchange_set_lab_test(self):
self.other_field = self.lab_test
2.
Related Field. Setup the child as a related field if it's of the same type:
child = fields.One2many(related='lab_test')
3.
Computed Field. Setup the child as a computed field with pulls whatever information you need.
child = fields.One2many(compute='_compute_child_field')

How to add null value to field Many2one from data file Odoo

I want to add a new category of Salary Structure by data file. Here is my current code
<record id="MEALS" model="hr.salary.rule.category">
<field name="name">Meals</field>
<field name="code">MEALS</field>
<field name="parent_id" eval=""></field>
</record>
All I need is a category with no parent category but with these code parent category of it is Base for new structures. I've tried with evals="0", evals = " " or remove field parent_id out of .How can I add null value into this field ?
This behaviour is a little weird .AFAIK If you don't include the parent_id field, it should work and have a null value because that field doesn't have a default value on it. (Except you've extended the model and added a default on that field).
The only fields where null values don't work in the Odoo ORM are Integer and float fields. (That's the reason they always have an initial value of 0 or 0.0 in a form view).
quoting the docs:
field
Each record can be composed of field tags, defining values to
set when creating the record. A record with no field will use all
default values (creation) or do nothing (update).
A field has a mandatory name attribute, the name of the field to set,
and various methods to define the value itself:
Nothing
if no value is provided for the field, an implicit False will
be set on the field. Can be used to clear a field, or avoid using a
default value for the field.
Try this <field name="parent_id" /> or <field name="parent_id" eval="False" />
If the above don't work then double check your codebase and make sure you're not setting any default value on the field.

How can I pass a context (in a view, in a field tag) from another field's value?

I want to create a many2one field which, in view, passes a context:
<field name="my_m2o_field" context="{'foo': 'bar'}" />
The goal here is to affect the related view (i.e. When you click on "Create and Edit" in a dropdown, you get a popup rendered by the related object's current view).
Such field tag works as expected if, in context, I have something like "{'default_code': 'my.code'}", provided code field exists in the related object.
However, the context I actually need is too large (20 entries), and I have to generate 5 contexts like that (with a minor diference, since I have 5 similar fields).
I would like to wrap the context in a -non-storable- functional field (I'd need, actually, 5 similar functional fields), and pass such context as value for the context attribute:
<field name="my_context_field" invisible="1" />
<field name="my_m2o_field" context="my_context_field" />
Is it possible? What type should I use (type= argument in the function constructor).