1

My first time publishing something here, hope it will work !

I'm trying to create a custom report in Odoo 11, in a custom module I did, I've followed the data I could gather but I can't get past the following problem.

  • So I created the Report like this :
      <report 
          id="production_order_report2"
          model="pb.orders.products"
          string="Production Order (English)"
          report_type="qweb-pdf"
          name="probespoketest.production_order_report_en2_template"
          file="probespoketest.production_order_report_en2_template"
          attachment_use="False"
      />
  • My Qweb report is :
  <template id="production_order_report_en2_template">
   <t t-call="web.html_container">
        <t t-foreach="docs" t-as="o">
            <t t-call="web.internal_layout">
                <div class="page">
                    <h2>Report title</h2>
                    <p>This object's name is</p>
                  <t t-esc="testing()"/>
                </div>
            </t>
        </t>
    </t>
      </template>
  • My python code is :
from odoo import api, fields, models, _

class OrderProductsFunctions(models.AbstractModel):
    _name = 'report.probespoketest.production_order_report_en2_template'

    def _testing(self):
      result = 0
        return result
  • My error is :
 Odoo Server Error
    Traceback (most recent call last):
      File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_qweb/qweb.py", line 342, in _compiled_fn
        return compiled(self, append, new, options, log)
      File "<template>", line 1, in template_1454_24554
      File "<template>", line 2, in body_call_content_24553
      File "<template>", line 3, in foreach_24552
      File "<template>", line 4, in body_call_content_24551
    TypeError: 'NoneType' object is not callable

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/opt/odoo/odoo11/addons/web/controllers/main.py", line 1617, in report_download
        response = self.report_routes(reportname, docids=docids, converter='pdf')
      File "/opt/odoo/odoo11/odoo/http.py", line 516, in response_wrap
        def response_wrap(*args, **kw):
      File "/opt/odoo/odoo11/addons/web/controllers/main.py", line 1566, in report_routes
        pdf = report.with_context(context).render_qweb_pdf(docids, data=data)[0]
      File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_actions_report.py", line 628,

in render_qweb_pdf html = self.with_context(context).render_qweb_html(res_ids, data=data)[0] File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_actions_report.py", line 666, in render_qweb_html return self.render_template(self.report_name, data), 'html' File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_actions_report.py", line 470, in render_template return view_obj.render_template(template, values) File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_ui_view.py", line 1195, in render_template return self.browse(self.get_view_id(template)).render(values, engine) File "/opt/odoo/odoo11/addons/web_editor/models/ir_ui_view.py", line 27, in render return super(IrUiView, self).render(values=values, engine=engine) File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_ui_view.py", line 1204, in render return self.env[engine].render(self.id, qcontext) File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_qweb/ir_qweb.py", line 57, in render return super(IrQWeb, self).render(id_or_xml_id, values=values, **context) File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_qweb/qweb.py", line 271, in render self.compile(template, options)(self, body.append, values or {}) File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_qweb/qweb.py", line 349, in _compiled_fn raise QWebException("Error to render compiling AST", e, path, node and etree.tostring(node[0], encoding='unicode'), name) odoo.addons.base.ir.ir_qweb.qweb.QWebException: 'NoneType' object is not callable Traceback (most recent call last): File "/opt/odoo/odoo11/odoo/addons/base/ir/ir_qweb/qweb.py", line 342, in _compiled_fn return compiled(self, append, new, options, log) File "", line 1, in template_1454_24554 File "", line 2, in body_call_content_24553 File "", line 3, in foreach_24552 File "", line 4, in body_call_content_24551 TypeError: 'NoneType' object is not callable

    Error to render compiling AST
    TypeError: 'NoneType' object is not callable
    Template: 1454
    Path: /templates/t/t/t/t/div/t
    Node: <t t-esc="testing()"/>

manifest.py and the two init.py should be ok but I can provide the code if needed.

Maybe the problem is that I should call the method testing() adding something. If I try to do :

> <t t-esc="docs.testing()"/>

Then I get :

> Error to render compiling AST AttributeError: 'pb.orders.products' object has no attribute 'testing' Template: 1454 Path:
> /templates/t/t/t/t/div/t Node: <t t-esc="docs.testing()"/>

Because my testing method is stored in another module that depends on the one I try to modify. But I don't know how to resolve this...

=== EDIT ===

@WaKo

Following your answer I coded this in my models.py (in the module where pb.orders.products is coded, aka "probespokeq") :

class OrderProductsFunctions(models.AbstractModel):
    _name = 'report.probespokeq.production_order_report_en2_template'
def _testing(self):
    result = 0
    return result

@api.model
def render_html(self, docids, data=None):
    report_obj = self.env['report']
    report = report_obj._get_report_from_name('probespokeq.production_order_report_en2_template')
    docargs = {
        'doc_ids': docids,
        'doc_model': report.pb.orders.products,
        'docs': self,
        'testing': self._testing,  # You need to add this line
    }
    return report_obj.render('probespokeq.production_order_report_en2_template', docargs)

Yet, I still have the same error message. Any idea ?

===== EDIT 2 ====

So, now I changed my class according to @WaKo suggestion with get_report_values instead of render_html so it looks like this :

class OrderProductsFunctions(models.AbstractModel):
    _name = 'report.probespokeq.production_order_report_en2_template'

    def _testing(self):
        result = 0
        return result

    @api.multi
  def get_report_values(self, docids, data=None):
      docs = self.env['pb.orders.products'].browse(docids)
      return {
          'doc_ids': docs.ids,
          'doc_model': 'pb.orders.products',
          'docs': docs,
          'testing': self._testing,  # You need to add this line
      }

So, now I change my xml as follows :

> <?xml version="1.0"?> <t
> t-name="probespokeq.production_order_report_en2_template">    <t
> t-call="web.html_container">
>         <t t-foreach="docs" t-as="o">
>             <t t-call="web.internal_layout">
>                 <div class="page">
>                     <h2>Report title</h2>
>                     <p>This object's name is probespokeq</p>
>                   <t t-esc="o.testing()"/>
>                 </div>
>             </t>
>         </t>
>     </t>      </t>

And I get :

> Error to render compiling AST AttributeError: 'pb.orders.products'
> object has no attribute 'testing' Template: 1455 Path:
> /templates/t/t/t/t/div/t Node:  <t t-esc="o.testing()"/>

1 Answer 1

0

To use testing in you report template like you did you should define it in a custom report parser and add it in docargs dict.

from odoo import api, models

class ParticularReport(models.AbstractModel):
    _name = 'report.module.report_name'

    def _testing(self):
        result = 0
        return result

    @api.model
    def render_html(self, docids, data=None):
        report_obj = self.env['report']
        report = report_obj._get_report_from_name('module.report_name')
        docargs = {
            'doc_ids': docids,
            'doc_model': report.model,
            'docs': self,
            'testing': self._testing,  # You need to add this line
        }
        return report_obj.render('module.report_name', docargs)

You can also define testing method in pb.orders.products and use o.testing() in your template.

You can find an example of a custom report which overwrites get_report_values function:

@api.multi
def get_report_values(self, docids, data=None):
    docs = self.env['pb.orders.products'].browse(docids)
    return {
        'doc_ids': docs.ids,
        'doc_model': 'pb.orders.products',
        'docs': docs,
        'testing': self._testing,  # You need to add this line
    }

Examples

To use a method from your model:

class PBOrdersProducts(models.Model):
    _name = "pb.orders.products"

    name = fields.Char()

    def testing(self):
        result = 0
        return result

And use:

<t t-esc="o.testing()"/>

In the template.

To use a custom parser like they did in sale module:

class ParticularReport(models.AbstractModel):
    _name = 'report.test.production_order_report'

    def _testing(self):
        result = 0
        return result

    @api.multi
    def get_report_values(self, docids, data=None):
        docs = self.env['pb.orders.products'].browse(docids)
        return {
            'doc_ids': docs.ids,
            'doc_model': 'pb.orders.products',
            'docs': docs,
            'testing': self._testing,  # You need to add this line
        }

And in this case you will need to use:

<t t-esc="testing()"/>  
Sign up to request clarification or add additional context in comments.

6 Comments

I edited my post according to your advice. Might I still be able to enquirer your help, please?
Use get_report_values instead of render_html and tell me what happened.
Did you use try the second function and added in the template file <t t-esc="testing()"/>to use it ?
Yes (I re edited the post). I tried with both <t t-esc="testing()"/> and <t t-esc="o.testing()"/> Sorry for the bothering and thanks for the help !
It's OK, Check my edit after Examples.I tested both methods and they worked.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.