3
votes

Is it possible to launch a ir.actions.act_window from a Python method of a model?. For instance, I have implemented a Session model which represents a course session (I also have a Course model). Also, I have a openacademy.xml where I have defined the form view to open the session form view.

<record model="ir.ui.view" id="session_form_view">
      <field name="name">session.form</field>
      <field name="model">openacademy.session</field>
      <field name="arch" type="xml">
        <form>
          <header>
            <button name="draft" type="workflow"
                    string="Reset to draft"
                    states="confirmed,done"/>
            <button name="confirm" type="workflow"
                    string="Confirm" states="draft"
                    class="oe_highlight"/>
            <button name="done" type="workflow"
                    string="Mark as done" states="confirmed"
                    class="oe_highlight"/>
            <button type="object"
                    name="my_method"
                    string="New course"/>
            <field name="state" widget="statusbar"/>
          </header>
          <sheet>
            <group string="General">
              <field name="name" string="Session name"/>
              <field name="course_id" string="Course"/>
              <field name="instructor_id" string="Instructor"/>
            </group>
            <group string="Management">
              <field name="start_date" string="Start date"/>
              <field name="active" string="Active"/>
              <field name="duration" string="Duration (in days)"/>
              <field name="seats"/>
              <field name="percent_taken_seats" widget="progressbar"/>
            </group>
            <label for="attendees"/>
            <field name="attendees"/>
          </sheet>
        </form>
      </field>
    </record>

The relevant part of the above code is the following:

<button type="object" name="my_method" string="New course"/>

When I click on this button a method 'my_method' from the Session model (class Session) is called.

class Session(models.Model):
...

    @api.one
    def my_method(self):
        return {
            'type': 'ir.actions.act_window',
            'res_model': 'openacademy.course',
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
        }

This method return a dictionary containing the differents keys and values of a window action, but it doesn't work in Odoo 8. When I click on the button "New course", my_method is executed but a Course form view is not opened to create a new Course record.

I don't know if it is possible to do this in Odoo version 8, or if my_method must return something more.

2

2 Answers

5
votes

The problem is with the decorator @api.one. The one decorator wrap the result of the method into a dict like this:

{res_id: result}

Which means that in your case, you're actually returning

{res_id: act_window}

Or in an array if you call it directly: [act_window]

Unfortunately, odoo expect to have the result itself (the actual thing that will get returned at some point).

In your case, you should instead use this:

@api.multi
def my_method(self):
    self.ensure_one()
    return {
        'type': 'ir.actions.act_window',
        'res_model': 'openacademy.course',
        'view_type': 'form',
        'view_mode': 'form',
        'target': 'new',
    }

self.ensure_one isn't particularly necessary in this case but what's really important is to use @api.multi. It doesn't wrap the result in anything and return exactly what you return as is unlike api.one.

Personally, I prefer to use api.multi because api.multi keeps things clean in all case. When I started to use @api.one I ended up in many place with things like:

val = self._compute_something()[0]

Where you have to get the first element because odoo wraps it into a list... while @api.multi is more flexible and if you really want to force it to be called with one element you can always use ensure_one.

3
votes

Try using @api.multi

I have coded functions that return a window action. The only difference from your code is my decorator. Otherwise, use a print in ur function as a debugging tool to make sure it gets called