Modify an existing handler

When you install the website module, the path /website/info displays some information about your Odoo instance. In this recipe, we override this in order to change this information page's layout, but also to change what is displayed.

Getting ready

Install the website module and inspect the path /website/info. Now craft a new module that depends on website and uses the following code.

How to do it…

We'll have to adapt the existing template and override the existing handler:

  1. Override the qweb template in a file called views/templates.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <odoo>
      <template id="show_website_info" inherit_id="website.show_website_info">
        <xpath expr="//dl[@t-foreach='apps']" position="replace">
          <table class="table">
            <tr t-foreach="apps" t-as="app">
              <th>
                <a t-att-href="app.website">
                <t t-esc="app.name" /></a>
              </th>
              <td><t t-esc="app.summary" /></td>
            </tr>
          </table>
        </xpath>
      </template>
    </odoo>
  2. Override the handler in a file called controllers/main.py:
    from openerp import http
    from openerp.addons.website.controllers.main import Website
    
    class Website(Website):
        @http.route()
        def website_info(self):
            result = super(Website, self).website_info()
            result.qcontext['apps'] = 
            result.qcontext['apps'].filtered(
                lambda x: x.name != 'website')
            return result

Now, when visiting the info page, we'll only see a filtered list of installed applications, and in a table as opposed to the original definition list.

How it works

In the first step, we override an existing QWeb template. In order to find out which that is, you'll have to consult the code of the original handler. Usually, it will end with the following command line, which tells you that you need to override template.name:

return request.render('template.name', values)

In our case, the handler uses a template called website.info, but this one is immediately extended by another template called website.show_website_info, so it's more convenient to override this one. Here, we replace the definition list showing installed apps with a table. For details about how QWeb inheritance works, consult Chapter 14, CMS Website Development.

In order to override the handler method, we must identify the class that defines the handler, which is openerp.addons.website.controllers.main.Website, in this case. We import the class to be able to inherit from it. Now we override the method and change the data passed to the response. Note that what the overridden handler returns is a Response object and not a string of HTML, as the previous recipes did for the sake of brevity. This object contains a reference to the template to be used and the values accessible to the template, but is only evaluated at the very end of the request.

In general, there are three ways to change an existing handler:

  • If it uses a QWeb template, the simplest way to change it is to override the template. This is the right choice for layout changes and small logic changes.
  • QWeb templates get a context passed, which is available in the response as the field qcontext. This is usually a dictionary where you can add or remove values to suit your needs. In the preceding example, we filter the list of apps to only contain apps which have a website set.
  • If the handler receives parameters, you could also preprocess those in order to have the overridden handler behave the way you want.

There's more…

As seen in the preceding section, inheritance with controllers works slightly differently than model inheritance: you actually need a reference to the base class and to use Python inheritance on it.

Don't forget to decorate your new handler with the @http.route decorator; Odoo uses it as a marker for which methods are exposed to the network layer. If you omit the decorator, you actually make the handler's path inaccessible.

The @http.route decorator itself behaves similarly to field declarations: every value you don't set will be derived from the decorator of the function you're overriding, so we don't have to repeat values we don't want to change.

After receiving a response object from the function you override, you can do a lot more than just changing the QWeb context:

  • You can add or remove HTTP headers by manipulating response.headers.
  • If you want to render an entirely different template, you can set response.template.
  • To detect if a response is based on QWeb in the first place, query response.is_qweb.
  • The resulting HTML code is available by calling response.render().

See also

  • Details of QWeb templates will be explained in Chapter 14, CMS Website development.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.172.93