Odoo中文社区可以通过以下两个域名访问:shine-it.net , odoo.net.cn

由于系统升迁的原因,本论坛部分较早期的内容存在格式和链接损坏失效的问题,并非本论坛系统本身的缺陷,望谅解

本社区没有维护任何QQ群讨论组,任何与本社区同名的QQ群讨论组的言论与本社区无关!

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

初学报表,不知从何处查错



  • 学习 把 社区这个模块 <br / [检测到链接无效,已移除] br />
    加了一个简单的报表,结果这报表 ,死活出不来。

    求教大家从何下手查错。


    lesson_view.xml

    <br />&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />&lt;openerp&gt;<br />&nbsp; &nbsp; &lt;data&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--定义表单视图--&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;record model=&quot;ir.ui.view&quot; id=&quot;oecn_training_lesson_from_view&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;name&quot;&gt;oecn.training.lesson.form&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;type&quot;&gt;form&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;model&quot;&gt;oecn.training.lesson&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;arch&quot; type=&quot;xml&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;name&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;date_start&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;total_day&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;price&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;teacher&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;students&quot; colspan=&quot;4&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;/record&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--定义列表视图--&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;record model=&quot;ir.ui.view&quot; id=&quot;oecn_training_lesson_tree_view&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;name&quot;&gt;oecn.training.lesson.tree&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;type&quot;&gt;tree&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;model&quot;&gt;oecn.training.lesson&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;arch&quot; type=&quot;xml&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;name&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;date_start&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;teacher&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;price&quot; sum=&quot;合计&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;/record&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--定义视图动作--&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;record model=&quot;ir.actions.act_window&quot; id=&quot;action_oecn_training_lesson&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;name&quot;&gt;oecn.training.lesson.action&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;res_model&quot;&gt;oecn.training.lesson&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;view_type&quot;&gt;form&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;view_mode&quot;&gt;form,tree&lt;/field&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field name=&quot;view_id&quot; ref=&quot;oecn_training_lesson_tree_view&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;/record&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--定义菜单--&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;menuitem id=&quot;oecn_menu&quot; name=&quot;OECN&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;menuitem id=&quot;oecn_training_menu&quot; name=&quot;OECN Training&quot; parent=&quot;oecn_menu&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;menuitem id=&quot;oecn_training_lesson_menu&quot; name=&quot;OECN training Lesson&quot; parent=&quot;oecn_training_menu&quot; action=&quot;action_oecn_training_lesson&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- Product_report 注释, 次文件定义报表的 ID 名称 菜单&nbsp; 对应 RML 文件 等等 <br />		下面这部分是我自己加上去的	<br />		--&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;report <br />			auto=&quot;False&quot; <br />			id=&quot;training_lesson_report&quot; <br />			model=&quot;oecn.training.lesson&quot; <br />			header=&quot;False&quot; <br />			name=&quot;oecn.training.lesson_report&quot; <br />			rml=&quot;oecn_training/report/oecn_training_lesson.rml&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string=&quot;课程报告&nbsp; Lesson report&quot;<br />		/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; &lt;/data&gt;<br />&nbsp; &nbsp; <br />&lt;/openerp&gt;<br />
    




    report_init_.py

    <br /># -*- encoding: utf-8 -*-<br />import report<br />import oecn_training_lesson_report<br />
    




    report\oecn_training_lesson_report.py

    <br /># -*- encoding: utf-8 -*-<br />import time<br />from report import report_sxw<br />from osv import osv<br /> <br />class training_lesson_report(report_sxw.rml_parse):<br />&nbsp; &nbsp; def __init__(self, cr, uid, name, context):<br />&nbsp; &nbsp; &nbsp; &nbsp; super(training_lesson_report, self).__init__(cr, uid, name, context)<br />&nbsp; &nbsp; &nbsp; &nbsp; self.localcontext.update({<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#039;time&#039;: time,<br />			&#039;instructor&#039;: self._print_instructor,<br />&nbsp; &nbsp; &nbsp; &nbsp; })<br /><br />&nbsp; &nbsp; def _print_instructor(self, seller_id):<br />&nbsp; &nbsp; &nbsp; &nbsp; return &#039;Toto&#039;<br /><br />report_sxw.report_sxw(&#039;report.oecn.training.lesson_report&#039;, &#039;oecn.training.lesson&#039;, &#039;addons/oecn_training_lesson/report/oecn_training_lesson_report.rml&#039;,<br />parser=training_lesson_report)<br /> <br /># vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:<br />
    



    report\oecn_training_lesson_report.rml

    <br />&lt;document filename=&quot;test.pdf&quot;&gt;<br />&nbsp; &lt;template pageSize=&quot;(595.0,842.0)&quot; title=&quot;Test&quot; author=&quot;Martin Simon&quot; allowSplitting=&quot;20&quot;&gt;<br />&nbsp; &nbsp; &lt;pageTemplate id=&quot;first&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &lt;frame id=&quot;first&quot; x1=&quot;57.0&quot; y1=&quot;57.0&quot; width=&quot;481&quot; height=&quot;728&quot;/&gt;<br />&nbsp; &nbsp; &lt;/pageTemplate&gt;<br />&nbsp; &lt;/template&gt;<br />&nbsp; &lt;stylesheet&gt;<br />&nbsp; &nbsp; &lt;blockTableStyle id=&quot;Standard_Outline&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &lt;blockAlignment value=&quot;LEFT&quot;/&gt;<br />&nbsp; &nbsp; &nbsp; &lt;blockValign value=&quot;TOP&quot;/&gt;<br />&nbsp; &nbsp; &lt;/blockTableStyle&gt;<br />&nbsp; &nbsp; &lt;initialize&gt;<br />&nbsp; &nbsp; &nbsp; &lt;paraStyle name=&quot;all&quot; alignment=&quot;justify&quot;/&gt;<br />&nbsp; &nbsp; &lt;/initialize&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;Standard&quot; fontName=&quot;Times-Roman&quot;/&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;Heading&quot; fontName=&quot;Helvetica&quot; fontSize=&quot;14.0&quot; leading=&quot;17&quot; spaceBefore=&quot;12.0&quot; spaceAfter=&quot;6.0&quot;/&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;Text body&quot; fontName=&quot;Times-Roman&quot; spaceBefore=&quot;0.0&quot; spaceAfter=&quot;6.0&quot;/&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;List&quot; fontName=&quot;Times-Roman&quot; spaceBefore=&quot;0.0&quot; spaceAfter=&quot;6.0&quot;/&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;Caption&quot; fontName=&quot;Times-Roman&quot; fontSize=&quot;12.0&quot; leading=&quot;15&quot; spaceBefore=&quot;6.0&quot; spaceAfter=&quot;6.0&quot;/&gt;<br />&nbsp; &nbsp; &lt;paraStyle name=&quot;Index&quot; fontName=&quot;Times-Roman&quot;/&gt;<br />&nbsp; &nbsp; &lt;images/&gt;<br />&nbsp; &lt;/stylesheet&gt;<br />&nbsp; &lt;story&gt;<br />&nbsp; &nbsp; &lt;para style=&quot;Standard&quot;&gt;Lesson information&lt;/para&gt;<br />&nbsp; &nbsp; &lt;para style=&quot;Standard&quot;&gt;[[repeatIn(objects,&#039;o&#039;)]]&lt;/para&gt;<br />&nbsp; &nbsp; &lt;para style=&quot;Standard&quot;&gt;<br />&nbsp; &nbsp; &nbsp; &lt;font color=&quot;white&quot;&gt; &lt;/font&gt;<br />&nbsp; &nbsp; &lt;/para&gt;<br />&nbsp; &nbsp; &lt;para style=&quot;Standard&quot;&gt;Name: [[o.name or &#039;&#039;]]&lt;/para&gt;<br />&nbsp; &lt;/story&gt;<br />&lt;/document&gt;<br />
    




    点击报表 菜单后直接就报错了

    <br /><br />Client Traceback (most recent call last):<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\addons\web\common\http.py&quot;, line 260, in dispatch<br />&nbsp; &nbsp; r = method(controller, self, **self.params)<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\addons\web\controllers\main.py&quot;, line 1784, in index<br />&nbsp; &nbsp; req.session._db, req.session._uid, req.session._password, report_id)<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\addons\web\common\openerplib\main.py&quot;, line 117, in proxy<br />&nbsp; &nbsp; result = self.connector.send(self.service_name, method, *args)<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\addons\web\common\http.py&quot;, line 596, in send<br />&nbsp; &nbsp; fault = xmlrpclib.Fault(&#039;warning -- &#039; + e.name + &#039;\n\n&#039; + e.value, &#039;&#039;)<br />TypeError: coercing to Unicode: need string or buffer, tuple found<br /><br />
    







    server log 如下:

    <br />2012-06-08 15:41:53,651 4620 INFO ? werkzeug: 127.0.0.1 - - [08/Jun/2012 15:41:53] &quot;POST /web/session/eval_domain_and_context HTTP/1.1&quot; 200 -<br />2012-06-08 15:41:53,822 4620 ERROR ? openerp.service.web_services: Exception: u&#039;report.oecn.training.lesson_report&#039;<br />Traceback (most recent call last):<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\service\web_services.py&quot;, line 709, in go<br />&nbsp; &nbsp; obj = netsvc.LocalService(&#039;report.&#039;+object)<br />&nbsp; File &quot;D:\3lp\studio\OpenERP\source6.1\server\openerp\netsvc.py&quot;, line 94, in LocalService<br />&nbsp; &nbsp; return Service._services[name]<br />KeyError: u&#039;report.oecn.training.lesson_report&#039;<br />2012-06-08 15:41:54,088 4620 ERROR ? openerp.netsvc: report.oecn.training.lesson_report<br />(&lt;type &#039;exceptions.KeyError&#039;&gt;, KeyError(u&#039;report.oecn.training.lesson_report&#039;,), &lt;traceback object at 0x06FDAE40&gt;)<br /><br />
    

  • 管理员

    感觉是你的报表没有注册到,是不是在report文件夹下的__init__.py没有import oecn_training_lesson_report?

    report_init_.py

    # -*- encoding: utf-8 -*-<br />import report<br />import oecn_training_lesson_report
    


    为什么这里还要 import report? 这个import report 应该放在上一级的__init__.py里面吧
    模块结构是怎样呢?



  • 跟踪代码看到的错误信息 确实是 报表没注册上去netsvc.LocalService('report.'+object)开始报错的

    我是在原来的教学模块 里依样画葫芦的 加了 报表。

    确实是  init.py 里面缺了 import report
    弄错地方了。




    改正后有进展,另外的错误了

    我继续 。。。。



  • 终于搞定 了,发现第二个错误,

    lesson_view.xml 中定义的 rml 路径和文件名错误,

    想不通为啥 要在两处(lesson_view.xml  和  report\oecn_training_lesson_report.py)都定义  rml  , 一样的东西,还希望高手们帮忙释疑


  • 管理员

    以你上面的代码为例:

    <br />&lt;report <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; auto=&quot;False&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id=&quot;training_lesson_report&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model=&quot;oecn.training.lesson&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; header=&quot;False&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name=&quot;oecn.training.lesson_report&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rml=&quot;oecn_training/report/oecn_training_lesson.rml&quot; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string=&quot;课程报告&nbsp; Lesson report&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; /&gt;<br />
    


    这一段是在 [检测到链接无效,已移除] 里添加一条记录,你可以通过进入 设定->自定义->底层对象->报表 可以查看到自己的报表

    <br />report_sxw.report_sxw(&#039;report.oecn.training.lesson_report&#039;, &#039;oecn.training.lesson&#039;, &#039;addons/oecn_training_lesson/report/oecn_training_lesson_report.rml&#039;,<br />parser=training_lesson_report)<br />
    


    这一段是实例化了report_sxw,实际上是通过这个实例来打印报表的。

    而你问的问题我们可以通过到report\report_sxw.py 代码里看看。

    <br />&nbsp; &nbsp; &nbsp; &nbsp; ir_obj = pool.get(&#039;ir.actions.report.xml&#039;)<br />&nbsp; &nbsp; &nbsp; &nbsp; report_xml_ids = ir_obj.search(cr, uid,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(&#039;report_name&#039;, &#039;=&#039;, self.name[7:])], context=context)<br />&nbsp; &nbsp; &nbsp; &nbsp; if report_xml_ids:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)<br />&nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title = &#039;&#039;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; report_file = tools.file_open(self.tmpl, subdir=None)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rml = report_file.read()<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; report_type= data.get(&#039;report_type&#039;, &#039;pdf&#039;)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; class a(object):<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def __init__(self, *args, **argv):<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for key,arg in argv.items():<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setattr(self, key, arg)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; report_xml = a(title=title, report_type=report_type, report_rml_content=rml, name=title, attachment=False, header=self.header)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; report_file.close()<br />
    


    这里的主要意思是他首先会根据名字report_name搜索 [检测到链接无效,已移除] ,如果有匹配的就取它的记录,如果没有就用上面实例化的那个实例。
    所以就是如果你向ir.actions.report.xml插入了报表数据 ,那么他就优先取它的数据而不是你在python里报表实例,这样的好处是你可以在openerp里面对报表直接进行修改(表头之类的),而不用修改代码。
    欢迎测试


Log in to reply