Get instances inside a classmethod for a button/action

How can I get one or more instances of an object inside the classmethod for a button/action?

The question occurs in the following use case: I want to set some fields of an instance in dependency of other fields when selecting a button/action in the client.

In the class definition I added the following code. Inside the classmethod my_button I cannot access to properties of an instance.

class MyClass (metaclass=PoolMeta):
	__name__ = 'myclass'
	
	my_property1 = fields.Char(
	  string='My Prop:',
	)
	
	my_property2 = fields.Char(
	  string='My Prop:',
	)
	
	@classmethod
	def __setup__(cls):
	  super().__setup__()
	  cls._button.update({
	    'my_button': {}
	  })
	
	@classmethod
	@ModelView.button
	def my_button(cls, objects):
	  
	  # I want to do something like this:
	  # self.my_property2 = self.my_property1 + 'some text'
	  # but cannot access to self.my_property1
	  
	  cls.write(objects, {
	    'my_property2': 'some text' # no access to content of my_property1
	  })

In the main XML file the button is defined with an record entry:

<tryton>
  <data>
  ...
  <record model="ir.model.button" id="my_button">
    <field name="name">my_button</field>
    <field name="string">My button</field>
    <field name="model" search="[('model','=','myclass')]">
  </record>
  </data>
</tryton>

Yes you can. The instance method receives a list of instances as first argument.
On your code I see you called such variable objects.

So you can do whatever you want with this instances in a for loop:

for record in objects: 
   your code here

Hope this helps!

Thanks for Your help! Three more questions:

  1. When I call my_button inside a form view, the list of objects has one instance element. Are there any cases, that the list of objects has more than one instance when calling my_button inside a form view?

  2. And if I would call my_button inside a tree view, would the list objects contain all instances shown in the tree view?

  3. I see two possibilities to save the changes in the instance. Do the two following statements inside my_button have the same meaning or are there any differences?

  • cls.write(objects, { 'my_property2' : record.my_property1 + 'some text' })
  • record.my_property2 = record.my_property1 + 'some text' ; record.save()

No, in this case objects will be allways a list of one record.

Same as point 1, it will only contain the record of the row you click on it.

It’s always better to use write method in a classmethod. AFAIK it will not make any difference in scnearios 1 and 2 because only one record will be modified but maybe in the future there are another scneario where you call the function from an action giving as argument more than one record. In this case it will be faster to use write method becaouse it will end on only one query unlike with record.save().

True, record.save() individually it’s slow compared to write all the objects.
But you can do a save in the Model which nearly there’s no difference in performance with the write:

for record in objects: 
    record.my_property2 = record.my_property1 + 'some text' 

cls.save(objects)

I also prefer this method than write as for me it’s more pythonic and versatile in the future to add new features on the button.

1 Like

Thanks for Your answers.