I know I can filter Many2one fields, from python code, or even xml views, with the domain flag, but I have a slightly different scenario right now,
Consider having a model like this:
class MyModel(models.Model):
_name = 'mymodel'
fieldsel = fields.Selection([('sheet', 'Sheet'),('reel','Reel')], string='Printing PPT Type',
track_visibility='onchange', copy=False,
help=" ")
fieldmany = fields.Many2one('text.paper', string="Text Paper")
The text.paper model has another Selection field, which has the same values as fieldsel, however, I cannot use domain since it will filter every text.paper statically.
My issue is, that I need to filter text.paper depending on which option I choose from fieldsel, so, let's say text.paper looks something like this:
class text_paper(models.Model):
_name = 'text.paper'
name = fields.Char(string="Code")
paper_type = fields.Selection([('sheet', 'Sheet'),('reel','Reel')], string="Paper Type")
I need to filter from mymodel the text.paper depending on the fieldsel field, if reel selected, filter text.paper which are reel, and if sheet selected, filter text.paper accordingly.
I hope I've explained myself.
Any ideas?
what you need is dynamic domain for many2one you can achive this by onchange event
class MyModel(models.Model):
_name = 'mymodel'
....
...
#api.onchange('fieldsel ')
def change_domain(self):
"""change the domain of fieldmany whenever the user changes the selected value."""
self.fieldmany = False # may be you want to reset the value when the user changes the selected value
if self.fieldsel : # make sure the user has selected a value
return {'domain': {fieldmany: [('paper_type', '=', self.fieldsel)]}}
else: # remove domain
return {'domain': {fieldmany: []}}
Related
I have an inherited model from res.partner.bank which i added a custom field called location to, this is how the model looks like.
class SalesPartnerBankInherit(models.Model):
_inherit = 'res.partner.bank'
location = fields.Char()
I have another inherited model from sale.order with a field that has a many2one relationship to res.partner.bank
I want to show only 1 record on the many2one dropdown if there are more than 1 records in res.partner.bank that has the same location field value?
This is my inherited sale.order model with the many2one location_id field
location_id = fields.Many2one('res.partner.bank',
string='Bank Account Location')
So if there are duplicate res.partner.bank records with the same location, I want to show only 1 record on the dropdown.
First, make your field compute then in compute method search all record from specific model and assign as per your requirement.
location_id = fields.Many2one('res.partner.bank', string='Meters', compute="_get_value")
def _get_value(self):
for i in self:
records = self.env['res.partner.bank'].search([], limit=1) # search with one record only from whole search and assign it.
i.location_id = records and records.id
hi am new to odoo development, this may be something simple but I can't figure it out
I added a new field subscription_tier to the sale.subscription model
class subscription_tire_set(models.Model):
_inherit = 'sale.subscription'
#api.depends('recurring_invoice_line_ids.product_id')
def _compute_subscription_tire(self):
# code for computing
n_subscription.subscription_tier = result
subscription_tier = fields.Char(string='Subscription Tier', readonly=True, compute='_compute_subscription_tire')
In my custom model, I added
#api.onchange('user_name')
def onchange_test_domain_fiedl(self):
obj = self.search([])
available_ids = []
for i in obj:
available_ids.append(i.user_name.id)
return {'domain': {'user_name': [&,|,('id', 'not in', available_ids),(('subscription_tier','=','tier_i'),('subscription_tier','=','tier_ii'),('subscription_tier','=','tier_iii'))]}}
user_name = fields.Many2one('sale.subscription', string='Name')
Instead of using multiple OR on one field, you can use domain in operator so the following domain:
['|', ('subscription_tier','=','tier_i'),'|', ('subscription_tier','=','tier_ii'),('subscription_tier','=','tier_iii')]
Can be reduced to :
[('subscription_tier','in', ['tier_i', 'tier_ii', 'tier_iii'])]
Computed fields are not stored by default, they are computed and returned when requested. Setting store=True will store them in the database and automatically enable searching. searching on a computed field can also be enabled by setting the search parameter.
Try to set subscription_tier store attribute to True to enable searching.
I want to get the field names in a model to be an option in a selection field in another model. Is it possible?
class ExportEmplWizard(models.TransientModel):
_name = 'hr.empl.exp.wizard'
empl_ids = fields.Many2many('hr.employee', string="Karyawan")
hr_field = fields.Selection(hr_field_choice, string="Pilih Kolom")
def empl_to_exp(self):
fields = self.env['hr.employee'].fields_get()
hr_field_choices = []
for key, val in fields.items():
choice = (key, val['string'])
hr_field_choices.append(choice)
I'm trying get fields name on other model using:
sel.self.env['hr.employee'].fields_get()
The problem is, i don't know how to make it as selection options (multiple selection actually).
Thank you for the help.
As per docstring for fields.Selection()
:param selection: specifies the possible values for this field.
It is given as either a list of pairs (value, string), or a
model method, or a method name.
Basically, the selection argument should work like the compute argument. And code of fields.Selection.get_values() confirms this.
So you should try something like this :
hr_field = fields.Selection(selection='empl_to_exp', string="Pilih Kolom")
def empl_to_exp(self):
fields = self.env['hr.employee'].fields_get()
return [(k, v['string']) for k, v in fields.items()]
You may have/want to use getattr(v, 'string', 'DEFAULT_VALUE') instead of simply v['string']. Fields should always have a string though.
def get_selection_name(env, model, field, value):
return dict(env[model].fields_get(field, 'selection').get(field, {}).get('selection',{})).get(value)
# usage
get_selection_name(request.env, 'sale.order', 'general_status', 'draft') # 'Draft'
get_selection_name(self.env, 'sale.order', 'general_status', 'draft') # 'Draft'
I use this!
I added 2 fields in 'sale.order.line' object. Let's say 'field1' and 'field2', those are readonly field. The value of the 2 fields will appear whenever the product is change in order line.
When I select a product, it shows the value of the two fields but when save it, the value will back 0, not stored.
Here's my code:
class sale_order_line(models.Model):
_inherit = 'sale.order.line'
field1 = fields.Float('One')
field2 = fields.Float('Two')
#api.multi
def product_id_change(self, pricelist, product, qty=0,
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False):
res = super(sale_order_line, self).product_id_change(pricelist, product, qty,
uom, qty_uos, uos, name, partner_id,
lang, update_tax, date_order, packaging, fiscal_position, flag)
if product:
one = self.search([('product_id', '=', product), ('partner_id', '=', partner_id)])
two = self.search([('product_id', '=', product), ('partner_id', '!=', partner_id)])
if customer:
field1 = one[-1]
res['value']['field1'] = field1
if other:
field2 = two[-1].
res['value']['field2'] = field2
return res
In Odoo framework we are now allowing to set readonly fields value, as well as readonly fields will not be getting in vals in create and write methods.
So if you set those readonly fields value in onchange methods then also it will not persist it's value because by nature it's readonly, it will not gives you any errors.
Purpose : The aims behind to define readonly attributes is to behave same through the all states of the record on UI and user can not change it's value and mainly define for display purpose.That is why readonly fields are not accessible for edit in onchange method.
Solution:
You need to override CREATE or WRITE method in following manner.
#api.model
def create(self, vals):
######
# WRITE YOUR LOGIC HERE AND BRING THOSE VALUE INTO VARIABLE AND THEN UPDATE IT IN VALS
VARIABLE_1 = SEARCH YOUR DATA
VARIABLE_2 = SEARCH YOUR DATA
vals.update({field1' : VARIABLE_1, 'field_2' : VARIABLE_2})
return super(sale_order_line, self).create(vals)
Update vals (record dictionary) by setting those readonly fields in to dictionary before calling super method or update those fields after calling super method.
There is an alternative solution for your problem. In Odoo Apps one module available from that system will store readonly value in the database.
Read Only ByPass
It is because readonly mode works only for display. In this case value from fields will not send to server-side.
You can override method create of sale.order.line. It should be something like this:
class sale_order_line(models.Model):
_inherit = 'sale.order.line'
#api.model
def create(self, vals):
# just example
vals[u'field1'] = 2.03
vals[u'field2'] = 3.05
return super(sale_order_line, self).create(vals)
Hope this helps you.
Hello to all I have been developing module under Odoo 8. I have a class "hrEmployee" with "_inherit=hr.employee" , now in my hrEmployee there is a One2many field having relation with another model "hr.employee.visa". I want to get the field values of the "hrEmployee" with onchange function defined on the field of "hr.employee.visa". Like when I change field value of "hrEmployee", I can get the field value entered on the current form (hrEmployee). How am I able to achieve this in Odoo v8? My Python code is shown below:
class hrEmployee(models.Model):
_inherit = "hr.employee"
diwan_no = fields.Char('Diwan No', size=30, help='Diwan Number')
zeo_number = fields.Char('ZEO Number',size=30, help='ZEO Number')
visas_ids = fields.One2many('hr.employee.visas', 'employee_id', 'Visas')
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
cr=self._cr
uid=self._uid
ids=self._ids
for id in ids:
obj1=self.pool.get('hr.employee').browse(cr,uid,id,context=None)
print obj1.name_related
visas_sponsor = fields.Char('Sponsor')
visas_states = fields.Selection([('apply','Apply'),('active','Active'),('expire','Expire'),('cancel','Cancelled')], string='State' )
visas_number = fields.Char('Visa No', help='Visa Number')
I tried to use self.pool.get browse but it gives me "False" . Plz guide me or point me my mistake. Hopes for suggestion
Try following,
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
for obj in self:
print obj.employee_id.name
Here is the mistake
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
You need to set hr.employee here.
No need to write both of the decorators together, in case of any changes into the visas_number field this method will be called, you can use any of the single decorator for this.