2

I am currently developing an odoo12ce module which must contains a table with dogs registers and its father and mother of the dogs (something like a purebred). In the field father_code I want to get just the male dogs and the ones who live in the same city.

get_domain_male(self):
  return [('gender', '=', 'male'), ('city', '=', self.city)]

father_code = fields.Many2one('asc.dog', string="Fathers code", domain = get_domain_male)

asc.dog is the same model, it means that the model is auto-referenced.

When I run the snippet, the city is already set and the field does not show anything, because self is not recognized as expected. When I print it, it is just False and the code run before I enter to the form view.

What could be wrong with the code and there is another way to filter it?? Thanks in advance for your help.

Jorge
  • 61
  • 3
  • 1
    You can't use the field value in a domain like that, `self` is an empty recordset and `self.city` will be evaluated to `False`. Use a string domain (``"[('gender', '=', 'male'), ('city', '=', city)]"``) which will be evaluated in the client-side and Odoo will render the domain and replace the field name with the field value from the current view. – Kenly Sep 19 '20 at 04:09
  • As Kenly said it's an empty record because this code is executed at view loading. You can use kenly suggestion when you use fields directly in domain, and onchange event when you need some calculations in your domains – Charif DZ Sep 20 '20 at 06:53
  • Is `city` a required field and therefor always set? – CZoellner Sep 22 '20 at 11:25
  • CZoellner yes it is always set, in the case of onchange, to get the data filtered I got to make a change on the seleccted field otherwise the data will not be filtered and what I looking for is to get the one2many field filtered at the load time. – Jorge Sep 23 '20 at 15:06

2 Answers2

2

From Odoo documentation

domain – an optional domain to set on candidate values on the client side (domain or string)

So, basically you can set domain as a string or list of tuples, in this case you can use string to set domain like this

father_code = fields.Many2one('asc.dog', string="Fathers code", 
  domain ="[('gender', '=', 'male'), ('city', '=', city)]")

So it will take city value from client side or view, and filter asc.dog records accordingly. Of course, to get values from client side, city field must exist in view or it will generate error the field not found in the view.

Optionally, instead of setting domain in Field definition, you can also setup domain in view definition.

<field name='city' />
<field name='father_code' domain="[('gender','=','male'),('city','=',city)]" />

Only difference is if you do it in the field definition, every view consisting father_code will always have this domain automatically set, but you must include city, visible or invisible.

arryph
  • 2,725
  • 10
  • 15
  • It's not clear if `city` is a required field, so if you wish, try to mention the `=?` domain operator as alternative. So if there is no city set on the "child dog" it would be possible to find every male dog as parent. When setting a city, Odoo will filter them by city too. But anyways: good answer. – CZoellner Sep 22 '20 at 11:28
  • Yeah good point, city may not be even set so `=?` operator will handle the unset situation . – arryph Sep 22 '20 at 14:25
1

Here we use an onchange field so that anytime the father field is changed the dog field is filtered.

It is almost always important to loop through records to avoid singleton and related issues.

@ api.onchange('father_code')
    def _onchange_father_code_filter_dog(self):
        for rec in self:
            return {'domain':
                    {'dog_field': [('gender', '=', 'male'), ('city', '=', rec.city)]}}
Eric
  • 940
  • 12
  • 27
  • You should use this technic only when you need some calculations in your domains, a string domain is enough – Charif DZ Sep 20 '20 at 06:56
  • what do you mean a string domain, what if you want to use self attribute? – Eric Sep 20 '20 at 15:43
  • `.. = fields....(....., domain="[('gender', '=', 'male'), ('city', '=', city)]")`. Everything will happen on the client side no need to trigger a sever call to calculate a domain that can be calculated in the client side. – Charif DZ Sep 20 '20 at 21:47
  • So when using the city element, the self attribute is already added? – Eric Sep 21 '20 at 12:20
  • Forget about self this value will be passed to client side, JavaScript will parse it and replace the variable city by the value of the field city in the view, it's the same when you do a domain in the view directly but when you do it in python it's applied to all views – Charif DZ Sep 21 '20 at 15:35
  • Not a bad answer, but wrong. The recalculate or onchange trigger is wrong. It should be `city` and not `father_code`, because changing the city will also change the domain/filter. – CZoellner Sep 22 '20 at 11:31