问题
How to pass multiple module data to a QWeb report? Is there something similar to passing dictionary in rendering html from controller?
class account(model.Models):
_name = 'account.main'
name = fields.Char()
class accountSub(model.Models):
_name = 'account.sub'
name = fields.Char()
class PrintWizard(model.Models):
_name = 'print.report'
account = fields.Many2one('erp.account')
@api.multi
def print_report(self):
ctx = self.env.context.copy()
ctx.update({'domain':[('name','=',self.account.name)]})
self.with_context(ctx)
return {'name': 'Report',
'type': 'ir.actions.report.xml',
'report_name': 'erp.report_id',
'report_type': 'qweb-pdf'}
class ErpReport(models.AbstractModel):
_name = "report.erp.report_id"
@api.multi
def print_report(self)
domain = self.env.context.get('domain')
print(domain) #Print result was None
main = self.env['account.main'].search(domain)
sub = self.env['account.sub'].search([])
docs = {
'docs1': main,
'docs2': sub,
}
return self.env['report'].render('erp.report', docs)
QWeb
<report
id="report_id"
string="Report"
model="erp.report"
report_type="qweb-pdf"
file="erp.report"
name="erp.report"
/>
<template id="payment_slip">
<t t-call="nationalerp_sales.erp_external_layout">
<t t-call="report.html_container">
<div class="page">
<div>
<t t-foreach="docs1" t-as="main">
<t t-esc="main.name"/>
</t>
<t t-foreach="docs2" t-as="sub">
<t t-esc="sub.name"/>
</t>
</div>
</div>
</t>
</t>
</template>
Passing data through context is not working. i tried to print the domain in abstract class it return none. but in my wizard it's okay
回答1:
If you want to run specific code before your report prints or pass custom data to your template for rendering you can create an Abstract model which defines a render_html
function so that your function will run when printing the report rather than the generic odoo function. This is referenced in the documentation
HERE
Take a look at this example.
from openerp import models, fields, api, exceptions
class YourReport(models.AbstractModel):
_name = 'report.your_addon.report_template_id'
@api.multi
def render_html(self, data=None):
report_obj = self.env['report']
report = report_obj._get_report_from_name('your_addon.report_template_id')
model1_docs = self.env['your_addon.your_model1'].search([('something','=','something')])
model2_docs = self.env['your_addon.your_model2'].search([('something','=','something')])
docargs = {
'doc_model': report.model,
'model1_docs': model1_docs,
'model2_docs': model2_docs,
}
return report_obj.render('your_addon.report_template_id', docargs)
UPDATE WITH MODIFIED CONTEXT:
To call your report with a modified context try the following (untested). I could not find any examples of calling reports with modified context however did not look extensively.
ctx = self.env.context.copy()
ctx.update({'domain':[('something','=','something')]})
self.with_context(ctx)
return {
'name':'Report',
'type':'ir.actions.report.xml,
'report_name':'your_addon.report_template_id',
'report_type':'qweb-pdf'
}
Then from within your report function we defined earlier you should be able to access context through your environment.
domain = self.env.context.get('domain')
You will need to create a function in your wizard which calls the report passing the context.
回答2:
Below is the code to create a custom Model report which is wrapped on v9 API. Creating custom object report is three step process
- Create RML Prase Custom Report Object
- Wrap RML Report to AbstractModel Report for qweb engine.
- Design template for the custom object.
- Register your under report registry.
All Four Part listed here with possible sample code.
RML Prase Custom Report Object
import time
from openerp.osv import osv
from openerp.report import report_sxw
class CustomReportPrint(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(CustomReportPrint, self).__init__(cr, uid, name, context=context)
self.localcontext.update({
'time': time,
'lst': self._lst,
'total': self._some_total,
'get_records':self._get_records,
})
def _get_records(self, res_ids):
records = self.pool.get('res.partner').browse(self.cr, self.uid, res_ids)
return records
def _lst(self, employee_id, dt_from, dt_to, max, *args):
#Your code goes here
return res
def _some_total(self, employee_id, dt_from, dt_to, max, *args):
#Your code goes here
return [result_dict]
Wrapping RML Prase Object tot he QWeb Engine.
class report_custom_print(osv.AbstractModel):
_name = 'report.<module_name>.report_custom_print'
_inherit = 'report.abstract_report'
_template = '<module_name>.report_custom_print'
_wrapped_report_class = CustomReportPrint
Report XML look as below as you can see I am calling get_records
from custom report model.
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="report_custom_print">
<t t-call="report.html_container">
<t t-foreach="get_records(data['form']['res_ids'])" t-as="employee">
<t t-call="report.internal_layout">
<div class="page">
<div class="oe_structure" />
</div>
</t>
</t>
</t>
</template>
</data>
</openerp>
Registering Report
<record id="action_report_custom_print" model="ir.actions.report.xml">
<field name="name">Custom Print Report</field>
<field name="report_type">qweb-pdf</field>
<field name="model">res.partner</field>
<field name="report_name"><module_name>.report_custom_print</field>
<field name="report_file"><module_name>.report_custom_print</field>
</record>
In custom Rml report Object you can define as many functions as you like and register them under __int__
and you can call those function directly on yor rpeort and mutpllate data as you need.
PS: replace with your module to make wit works correct.
Hope this will help.
来源:https://stackoverflow.com/questions/40290627/custom-report-through-python-odoo-9