How to call python function from QWeb Report

If you want to call a python function from the QWeb report you will need to create a custom parser for the report. In the parser, you will need to add the function as an argument in the render method.

For Example, if you need to add custom function that will return split text in the Sale Order report the code for the parser should look like following:

from openerp import api, models


def split_text(txt):
    return txt.split(';')

class SaleOrderReport(models.AbstractModel):
    _name = 'report.sale.report_saleorder'

    @api.multi
    def render_html(self, data=None):
        report = self.env['report']._get_report_from_name('sale.report_saleorder')

        docargs = {
            'doc_ids': self._ids,
            'doc_model': report.model,
            'docs': self.env['sale.order'].browse(self._ids),
            'split_text': split_text
            }

        return self.env['report'].render('sale.report_saleorder', docargs)

Now when you have the method split_text in the list of arguments you can access it in the report like:

<xpath expr="//p[@t-field='doc.note']" position="replace">
    <t t-foreach="split_text(doc.note)" t-as="text_line">
        <p t-esc="text_line.strip()"/>
    </t>
</xpath>

Additionally, you can find an example of the code as simple module here

13 Comments

  1. Ged

    Hello could you tell me a bit more about your code. Where do you put the main code? in sale_report.py? or can you install as module? i have tried to make custom module, then i have added inside the report, but it gives me an error.

    1. admin

      Hi Ged,
      Yeah, you should create a custom module in which you need to add a custom parser for the report. What that means is in your odoo module create new python module where you will add the code from the example. I have changed the name of the report in the example to match the name of the default Sales Order Report. After that, you can override the XML part of the report and use the method split_test in it.
      If you still getting an error let me know the error message and I will try to help you.

  2. Ged

    Hello there, here is my code(took an example directly from odoo page):

    class buh_aps_report(models.AbstractModel):
    _name = ‘report.l10n_lt_buh_aps_forma.report_buh_aps_forma_lt’

    def some_math(txt):
    return txt * 5

    def get_format(self):
    return ‘its working’

    @api.multi
    def render_html(self, data=None):
    report_obj = self.env[‘report’]
    report = report_obj._get_report_from_name(‘l10n_lt_buh_aps_forma.report_buh_aps_forma_lt’)
    docargs = {
    ‘doc_ids’: self._ids,
    ‘doc_model’: report.model,
    ‘docs’: self,
    ‘some_math’: self.some_math,
    ‘get_format’: self.get_format,
    }
    return report_obj.render(‘l10n_lt_buh_aps_forma.report_buh_aps_forma_lt’, docargs)

    After i add this code to my module i cant access all object attributes, actually i can but only from report.l10n_lt_buh_aps_forma.report_buh_aps_forma_lt model ,which are: id, display_name, __last_update.

    And im getting error like this:

    “‘report.l10n_lt_buh_aps_forma.report_buh_aps_forma_’ object has no attribute ‘line_ids'” while evaluating ‘o.line_ids’

    If you need i can post my report code as well. Thank you

  3. bil

    from odoo import api, models

    import logging
    _logger = logging.getLogger(__name__)

    class pet_report(models.AbstractModel):
    _name = ‘report.pet.report_pet_qweb’
    _template = ‘pet.report_pet_qweb’

    def get_pet_price(self, petname):
    price = 87.77 #hardcording for testing only
    return price

    @api.model
    def render_html(self, docids, data=None):
    pet_obj = self.env[‘tbl.pets’].browse(docids)

    docargs = {
    ‘doc_ids’: docids,
    ‘doc_model’: ‘tbl.pets’,
    ‘data’: data,
    ‘docs’: pet_obj,
    ‘get_pet_price’:get_pet_price,

    }
    return self.env[‘report’].render(‘pet.report_pet_qweb’, docargs)

    with the above code in Odoo 10 I am getting runtime error
    “QWebException: ‘NoneType’ object is not callable
    Traceback (most recent call last):
    .
    .
    Node: ”

    If I comment out my report runs

    1. admin

      Hi Bil,

      As I can see “get_pet_price” is part of the class “pet_report” and should be called with “self”, but in the docargs it is defined as ‘get_pet_price’:get_pet_price,.

      Correct version should look like:
      docargs = {
      ‘doc_ids’: docids,
      ‘doc_model’: ‘tbl.pets’,
      ‘data’: data,
      ‘docs’: pet_obj,
      ‘get_pet_price’:self.get_pet_price,
      }

  4. Ged

    Could you post your code as a ready made module? because i have tried your code today, and it doesn’t work. Tried example from Odoo documentation, it brings me empty pdf. Working example code would be very nice. Thank you

        1. admin

          You can not install this module on v10 because it is for v9. Will migrate it today. But in any case, the way of calling python method in the QWeb reports is the same.

Leave a Reply

Your email address will not be published.