I have the following situation: If the name attribute of my student object changes, I want to keep the old value and save it to another table.
So, If I have a student object with the name attribute 'John 1', after a student.update_attributes(:name => 'John 2') I want to be able to capture the old name value 'John 1' in a before_update callback hook, for instance. What's the best way to do that ? Thanks in advance.
In the before_update hook, you can access special _was methods to get the previous value of each field
before_update do
new_name = self.name # 'John 2'
old_name = self.name_was # 'John 1'
end
Related
I'm trying to lookup some data in my database using a string, but utilizing multiple json keys to check in.
I know you can lookup using a single key in this case 'name'
SELECT *
FROM products_product
WHERE data->>'name' IN ('Value 1', 'Value 2')
My issue is that i have two types of json values being saved and therefore need to check both 'name' and 'title'
As an example to simplify it:
{
"name": "Value 1"
}
while the second maybe looking like this:
{
"title": "Value 2"
}
How can i do a single query check both 'name' and 'title' for the values i got?
I was expecting maybe to be able to do something like
SELECT *
FROM products_product
WHERE data->>('name', 'title') IN ('Value 1', 'Value 2')
But its not possible!
Would want to avoid having to do multiple queries as i know the keys the data can be placed in and got them as a list or tuple (whatever is needed)
So my final question is:
How can i query the database to check multiple fields (if they exist) for the values i have defined?
I'm expecting both the examples to be returned in a single query and not just one of them
You can use an OR
SELECT *
FROM products_product
WHERE data->>'name' IN ('Value 1', 'Value 2')
OR data->>'title' IN ('Value 1', 'Value 2')
You can slightly simplify this, by only specifying the values once:
with input (val) as (
values ('Value1'), ('Value2') --<< note the parentheses!
)
SELECT *
FROM products_product
WHERE data->>'name' IN (select val from input)
OR data->>'title' IN (select val from input)
You don't say what version you are using. You can do this with json path in postgres 12. The syntax is a bit obtuse, but it's possible:
SELECT * FROM products_product
WHERE jsonb_path_exists(data,
'strict $.keyvalue() ? ((#.value == "Value 1" || #.value == "Value 2") && (#.key == "name" || #.key == "title"))');
This will search every key/value combo at the root of your object and look for keys equalling name or title and values equalling Value 1 or Value 2.
Can I select some data fields from different models and display these fields in my tree view, then I modify my selection and persist in other models?
'#api.v8
def get_data(self):
data = self.env['my.models]].browse(id)'
There are 3 ways to provide selection list values that is accepted by OpenERP:
Specifying directly in the field.selection definition: 'field_1':
fields.selection([('value1', 'String 1'), ('value2', 'String 2')],
'Field Label')
Specifying using a name list variable outside of the field.selection
definition: 'field_1': fields.selection(LIST_VARIABLE, 'Field
Label'). Where LIST_VARIABLE is defined beforehand: LIST_VARIABLE =
[('value1', 'String 1'), ('value2', 'String 2')]
Specifying using a method: 'field_1': fields.selection(_method_name,
'Field Label'). Where _method_name is defined beforehand:
def _method_name(self, cr, uid, context=None):
return [('value1', 'String 1'), ('value2', 'String 2')]
Now, you need to check first which one is your current selection field is. If it is using method No. 1, then you need to redefine it to use either method No 2 or method No 3. If it is using method No. 2 or 3, you just need to change either the variable (you can use LIST_VARIABLE.append(('value3', 'String 3'))) to return the new value.
I have tried below code for onchange function but return some unreadable code
class sales_targets(models.Model):
_name = 'sale.target'
category = fields.Selection([
('normal', 'Product'), ('cloud', 'Cloud EYE'), ('tech', 'Technical Support Group'), ('db', 'Database'),
('odoo', 'Odoo'), ('can', 'CAN'), ('tod', 'TOD'), ('rental', 'Rental'), ('tec', 'TEC'), ('top', 'TOP'),
('tor', 'TOR'), ('tos', 'TOS'),
('aws', 'AWS')], 'Category', default='normal',
help="A category of the view type is a virtual category that can be used as the parent of another category to create a hierarchical structure.")
team_ids=fields.Many2many('crm.team','team_target_rel','target_ids','team_id','Sales Team')
from_date=fields.Date('Budget From Date')
to_date = fields.Date('Budget To Date')
no_call=fields.Float('No of Calls')
target_line=fields.One2many('target.line','target_id','Target Line', copy=True)
#api.multi
#api.onchange('team_ids')
def _onchange_tem_salesperson(self):
print ".....",self.id,self._origin
above code onchange function result is
...... <odoo.models.NewId object at 0x7f72aff2b290> sale.target()
In onchange event odoo create a dummy record for you.
In order to get the id, odoo passes the record in origin property.
self._origin.id. # keep in mind in create id is instance of NewId object Not integer
I'm not sure if it's self. _origin or self.origin but i'm sure that it's in origin because i used it before. Hope it helped you
thanks for you advice and then finally got solution for this page How to pass value with onchange one2many variable in odoo? please up vote my question if my question is worth
Using a PG database filled with registered voters.
Trying to set it up so I can search by first name, last name, zip or city. I want to be able to find all voters that match all of the entered params, but having trouble dealing with empty search fields.
where("zip LIKE ? OR city LIKE ? OR last_name LIKE ? OR first_name LIKE ?",
"#{params[:zip]}","#{params[:city]}","#{params[:last_name]}","#{params[:first_name]}")
Is there a better way to build it out so that it matches ALL entered parameters, but ignores empty string parameters? Right now if I enter a first and last name 'John Smith' I will get 'John Jones' and 'Jane Smith'.
This can do the trick:
attrs_name_to_search = %w( zip city last_name first_name )
fitlered_params = params.slice(*attrs_name_to_search).select { |_,v| v.present? }
sql_cond = filtered_params.map { |k,_| "#{k} LIKE :#{k}" }.join(' OR ')
YourModel.where(sql_cond, filtered_params)
But it should return all the records if no zip/city/last_name/first_name is given.
I have to create a selection field based on other column. i mean the data comes from other table but based on current table column value. so i created a selection field as below:
pull_location = fields.Selection(selection='_get_pull_locations',string='Pull Location')
and the function is as below:
#api.multi
def _get_pull_locations(self):
data=[]
** Get the values from other table based on current record **
return [('value1', 'String 1'), ('value2', 'String 2')]
Always when i debug i get self as empty class object ( stock.test()). the scenario is i have a column named zone in stock.test, i have another table called stock.location, so for current record i check the stock.location table where column pull_zone == zone of stock.test and if yes append the selection (pull_location) with that values.
But always the object is empty.
I tried #api.one, #api.multi, #api.model , Nothing happens.
Please help.
Thanks,
Replace your code with following:
#api.multi
def _get_pull_locations(self):
** Get the values from other table based on current record **
return [
('value1', 'String 1'),
('value2', 'String 2')
]
pull_location = fields.Selection('_get_pull_locations', string='Pull Location')
Afterwards, Restart Odoo server and upgrade your module.