Odoo 8自定义模块出现MissingError,求解决方案
Odoo 8自定义模块MissingError问题分析与解决
错误现象
在Odoo 8的自定义模块中触发MissingError,错误提示:
您尝试访问的某一文档已被删除,请刷新后重试。
完整错误栈
File "C:\Tunas_Ridean\Odoo-8.0\addons\sale\sale.py", line 1067, in product_id_change if product_obj.taxes_id: File "C:\Tunas_Ridean\Odoo-8.0\openerp\fields.py", line 840, in __get__ return record._cache[self] File "C:\Tunas_Ridean\Odoo-8.0\openerp\models.py", line 6041, in __getitem__ return value.get() if isinstance(value, SpecialValue) else value File "C:\Tunas_Ridean\Odoo-8.0\openerp\fields.py", line 56, in get raise self.exception MissingError: ('MissingError', u'One of the documents you are trying to access has been deleted, please try again after refreshing.')
自定义模块代码
模型文件 models/sale_order.py
# models/sale_order.py from openerp import models, fields from openerp import api class SaleOrderLine(models.Model): _inherit = 'sale.order.line' product_id = fields.Many2one( 'product.custom', string='Product', required=True, domain=[('state', 'in', ['confirmed', 'approved'])] ) price_unit = fields.Float( string='Price Unit', related='product_id.price', # Mengambil harga dari `product.custom` store=True, readonly=True ) @api.onchange('product_id.price','price_unit') def _onchange_product_id(self): #import ipdb; ipdb.set_trace() self.price_unit = self.product_id.price self.name = self.product_id.description self.product_uom_qty = self.product_id.qty
视图文件 views/sale_order_view.xml
<!-- views/sale_order_view.xml --> <openerp> <data> <record id="view_order_form_custom" model="ir.ui.view"> <field name="name">sale.order.form.inherit</field> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_order_form"/> <field name="arch" type="xml"> <xpath expr="//field[@name='product_id']" position="replace"> <field name="product_id"/> </xpath> <xpath expr="//field[@name='price_unit']" position="attributes"> <attribute name="readonly">1</attribute> </xpath> </field> </record> </data> </openerp>
问题根源
原生sale模块的sale.order.line模型中,product_id字段关联的是product.product,且自带product_id_change方法处理产品变更逻辑。你在自定义模块中继承sale.order.line后,将product_id的关联模型替换为了product.custom,但原生的product_id_change方法仍会被触发——该方法会尝试用product.product模型去读取当前product_id对应的记录(实际是product.custom的ID),自然找不到对应文档,从而抛出MissingError。
另外,你的@api.onchange装饰器监听字段有误,product_id.price不是可直接监听的字段,应该监听product_id本身。
解决方案
1. 重写product_id_change方法,覆盖原生逻辑
在自定义的SaleOrderLine类中重写该方法,适配product.custom模型,避免原生逻辑报错:
# models/sale_order.py from openerp import models, fields, api class SaleOrderLine(models.Model): _inherit = 'sale.order.line' product_id = fields.Many2one( 'product.custom', string='Product', required=True, domain=[('state', 'in', ['confirmed', 'approved'])] ) price_unit = fields.Float( string='Price Unit', related='product_id.price', # 从product.custom获取价格 store=True, readonly=True ) @api.onchange('product_id') def _onchange_product_id(self): if not self.product_id: return self.price_unit = self.product_id.price self.name = self.product_id.description self.product_uom_qty = self.product_id.qty # 重写原生product_id_change方法,适配自定义产品模型 def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): res = {'value': {}} if product: # 用自定义产品模型读取记录 product_obj = self.pool.get('product.custom').browse(cr, uid, product, context=context) # 自定义字段赋值逻辑 res['value']['name'] = product_obj.description res['value']['price_unit'] = product_obj.price # 若需要处理税务等其他逻辑,可在此添加适配代码 return res
2. 修正视图XPath表达式
原生sale.order.form中的product_id字段位于订单行的子视图内,原XPath表达式可能无法精准定位,建议修改为:
<xpath expr="//field[@name='order_line']//field[@name='product_id']" position="replace"> <field name="product_id"/> </xpath>
3. 调整onchange监听字段
将@api.onchange('product_id.price','price_unit')改为@api.onchange('product_id'),只有当产品本身变更时才触发逻辑,避免无效监听。
内容的提问来源于stack exchange,提问作者Ananda Rauf Maududi
相关产品推荐
相关产品推荐

