Reputation: 13
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.
<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" />
<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>
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
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()"/>
Upvotes: 1
Views: 13720
Reputation: 26748
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()"/>
Upvotes: 0