如何在Odoo 8中通过Python将原生查询数据生成列表视图?
在Odoo 8里实现这个需求其实很 straightforward,核心是通过ir.actions.act_window动作关联对应模型和视图,结合你已经写的原生查询过滤数据。下面分两种常见实现方式,你可以根据需求选择:
方法一:利用系统自带的stock.move模型和视图(推荐)
这种方式不需要额外创建新模型和视图,直接复用Odoo内置的库存移动模型和视图,只需要过滤出当前采购订单对应的记录即可。
1. 完善按钮触发的方法(在purchase.order模型中)
from openerp import models, fields, api, _ from openerp.exceptions import Warning class PurchaseOrder(models.Model): _inherit = 'purchase.order' @api.multi def action_view_stock_moves(self): # 确保只处理单条采购订单记录 self.ensure_one() po_name = self.name # 执行原生查询,只获取库存移动的ID即可(后续用domain过滤更高效) self.env.cr.execute("SELECT id FROM stock_move WHERE origin=%s", (po_name,)) move_ids = [row[0] for row in self.env.cr.fetchall()] if not move_ids: raise Warning(_("No stock moves found for this purchase order.")) # 返回act_window动作,指向stock.move的列表视图 return { 'name': _('Stock Moves for %s') % self.name, 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'tree,form', # 先展示列表,可切换到表单 'res_model': 'stock.move', # 指定要展示的模型 'domain': [('id', 'in', move_ids)], # 过滤出当前采购订单对应的记录 'target': 'current', # 在当前标签页打开,换成'new'则是新标签页 'context': self.env.context, }
2. 确认表单视图中的按钮定义(如果还没配置好)
在采购订单的表单视图XML中,确保按钮的name属性和上面的方法名一致:
<button name="action_view_stock_moves" string="View Stock Moves" type="object" class="oe_highlight"/>
方法二:创建临时模型展示自定义数据(适合特殊需求)
如果需要自定义展示字段或者对查询结果做特殊处理,可以创建一个临时的transient模型来存储查询数据,再为这个模型创建对应的列表视图。
1. 创建临时模型
from openerp import models, fields, api class TempStockMove(models.TransientModel): _name = 'temp.stock.move' _description = 'Temporary Stock Move Records' # 定义需要展示的字段,对应stock_move表中的字段 name = fields.Char(string='Move Name') product_id = fields.Many2one('product.product', string='Product') product_uom_qty = fields.Float(string='Quantity') location_id = fields.Many2one('stock.location', string='Source Location') location_dest_id = fields.Many2one('stock.location', string='Destination Location')
2. 修改按钮触发方法,填充临时模型数据
@api.multi def action_view_stock_moves(self): self.ensure_one() po_name = self.name # 执行原生查询,用dictfetchall获取字典格式的数据,方便后续赋值 self.env.cr.execute("SELECT * FROM stock_move WHERE origin=%s", (po_name,)) s_moves = self.env.cr.dictfetchall() if not s_moves: raise Warning(_("No stock moves found for this purchase order.")) # 清空之前的临时数据(避免残留) temp_move_model = self.env['temp.stock.move'] temp_move_model.search([]).unlink() # 将查询结果填充到临时模型中 for move in s_moves: temp_move_model.create({ 'name': move.get('name'), 'product_id': move.get('product_id'), 'product_uom_qty': move.get('product_uom_qty'), 'location_id': move.get('location_id'), 'location_dest_id': move.get('location_dest_id'), # 其他需要展示的字段,对应stock_move表中的字段名 }) # 返回act_window动作,指向临时模型的列表视图 return { 'name': _('Stock Moves for %s') % self.name, 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'tree', 'res_model': 'temp.stock.move', 'target': 'new', 'context': self.env.context, }
3. 为临时模型创建列表视图
<record id="view_temp_stock_move_tree" model="ir.ui.view"> <field name="name">temp.stock.move.tree</field> <field name="model">temp.stock.move</field> <field name="arch" type="xml"> <tree string="Stock Moves"> <field name="name"/> <field name="product_id"/> <field name="product_uom_qty"/> <field name="location_id"/> <field name="location_dest_id"/> <!-- 添加更多你需要展示的字段 --> </tree> </field> </record>
注意事项
- 第一种方法更简洁高效,推荐优先使用,因为它复用了Odoo内置的模型和视图,不需要额外维护代码。
- 如果你用原生查询获取了所有字段,记得要和模型字段对应上,避免赋值错误。
- Odoo 8中使用
@api.multi装饰器,确保方法支持多记录操作,再用self.ensure_one()限制为单条记录处理。
内容的提问来源于stack exchange,提问作者Shahjalal
相关产品推荐
相关产品推荐

