Odoo - 列表视图中的点击事件自定义
Odoo - Click event customization in list view
我已经在 _auto = False
的 psql 查询的帮助下创建了一个列表视图。所以没有针对此注册的模型。现在我想在记录上自定义此点击事件,每当用户点击我想传递的任何记录时 order_id 然后将用户重定向到该特定订单详细信息屏幕。
编辑
查看
<odoo>
<data>
<record id="amgl_dashboard_tree" model="ir.ui.view">
<field name="name">Dashboard</field>
<field name="model">amgl.dashboard</field>
<field name="arch" type="xml">
<tree default_order="state desc" decoration-bf ="state in ('expecting','pending','completed')" decoration-info="state=='expecting'" decoration-danger="state=='pending'" decoration-succes="state=='completed'" string="Dashboard" create="false" edit="false">
<field name="order_id" invisible="1"/>
<button name="view_record" type="object" string="View Record" custom="click" class="oe_highlight"/>
<field name="first_name"/>
<field name="last_name"/>
<field name="account_number"/>
<field name="product"/>
<field name="quantity"/>
<field name="total_weight"/>
<field name="state"/>
</tree>
</field>
</record>
</data>
</odoo>
.py
class Dashboard(models.Model):
_name = 'amgl.dashboard'
_auto = False
@api.multi
def view_record(self):
print self
@api.model_cr
def init(self):
tools.drop_view_if_exists(self._cr, 'dashboard')
self._cr.execute("""
CREATE or REPLACE VIEW amgl_dashboard AS (
SELECT
row_number() OVER () AS id,
c.name AS first_name,
c.last_name AS last_name,
c.account_type AS account_type,
c.account_number AS account_number,
(select name from amgl_products where id = ol.products) AS product,
ol.quantity AS quantity,
(CASE
WHEN (select weight_unit from amgl_products where id = ol.products) = 'oz'
THEN
(select weight_per_piece from public.amgl_products where id = ol.products) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'gram'
THEN
((select weight_per_piece from public.amgl_products where id = ol.products) / 28.34952) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'pounds'
THEN
((select weight_per_piece from amgl_products where id = ol.products) * 16) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'kg'
THEN
((select weight_per_piece from amgl_products where id = ol.products) / 0.02834952) * ol.quantity
ELSE 0.0
END) AS total_weight,
o.state AS state,
o.id AS order_id
FROM amgl_order AS o
INNER JOIN amgl_customer AS c ON c.id = o.customer_id
INNER JOIN amgl_order_line AS ol ON ol.order_id = o.id
)""")
name = fields.Char()
first_name = fields.Char(string="First Name")
last_name = fields.Char(string="Last Name")
account_type = fields.Char(string="Account Type")
account_number = fields.Char(string="Account Number")
product = fields.Char(string="Product")
quantity = fields.Float(string="Quantity")
total_weight = fields.Float(string="Total Weight")
state = fields.Selection([('expecting', 'Expecting'), ('pending', 'Pending'),
('completed', 'Completed'), ('waiting', 'Waiting For Approval')],
'Status', default='expecting')
order_id = fields.Integer(string="Order Id")
动作
<record id="amgl.dashboard_action_window" model="ir.actions.act_window">
<field name="name">Dashboard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">amgl.dashboard</field>
<field name="view_mode">tree</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
<!-- Add Text Here -->
</p><p>
<!-- More details about what a user can do with this object will be OK -->
</p>
</field>
</record>
调试器
Self._context
Self
当您单击 listview
上的记录时,会执行一个操作,将您从 listview
移至 `formview。
默认操作始终存在,但如果您想传递一些额外参数,则必须定义您自己的参数。有关具体示例,请查看 sale.action_quotations
操作。此操作将用户从视图 1 移动到视图 2(例如列表到表单)
https://github.com/OCA/OCB/blob/10.0/addons/sale/views/sale_views.xml#L518
<record id="action_quotations" model="ir.actions.act_window">
...
<field name="context">{'hide_sale': True}</field>
...
</record
此操作负责在视图之间移动报价单中的用户。查看上下文是如何传递的。你只需要在 view_mode
上 tree,form
即可。
我认为有几种方法可以可能起作用。我不是 100% 肯定他们中的任何一个,但我会给你一般的想法。
XML唯一的解决方案
George 的主要想法是正确的 - 您需要创建一个操作来管理您想要做的事情。
重要的区别在于您似乎希望列表视图显示一个模型 (amgl.dashboard
) 而表单视图显示另一个模型 (sale.order
)
通常,我建议您创建一个 button
并将其显示在列表视图中,以便将用户直接带到销售订单表单。但是,您也可以在 src_model
的帮助下使用标准 act_window
操作。
核心示例:
Odoo 使用下面的按钮调用操作,这导致用户能够转到 stock.location
表单视图并转到 product.product
列表。您本质上是想在没有按钮的情况下使用不同的模型来执行与此相反的操作。
<button string="Products"
class="oe_stat_button"
icon="fa-filter" name="%(act_product_location_open)d" type="action"
context="{'location_id': active_id}"
/>
<act_window
id="act_product_location_open"
name="Products"
src_model="stock.location"
res_model="product.product"
context="{'location': active_id,
'search_default_real_stock_available': 1,
'search_default_virtual_stock_available': 1,
'search_default_virtual_stock_negative': 1,
'search_default_real_stock_negative': 1}"/>
Python 解法:
假设您的 view_record
方法已经被调用,您可以直接从方法本身 return "View Sales Order form" 操作。
# Make sure these imports are called in your file
# If you are on Odoo 9 or earlier, you must use openerp instead of odoo
from odoo import _
from odoo.exceptions import ValidationError
class Dashboard(models.Model):
_name = 'amgl.dashboard'
_auto = False
@api.multi
def view_record(self):
"""Return a Window Action to view the Sales Order form"""
self.ensure_one()
action = self.env.ref('sale.action_orders')
form = self.env.ref('sale.view_order_form', False)
if not (action or form):
raise ValidationError(_("Sales Orders Action or Form not found!"))
return {
'name': action.name,
'help': action.help,
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'views': [(form_id.id, 'form')]
'res_model': action.res_model,
'res_id': self._context.get('id'),
'target': 'current',
'context': {},
}
我已经在 _auto = False
的 psql 查询的帮助下创建了一个列表视图。所以没有针对此注册的模型。现在我想在记录上自定义此点击事件,每当用户点击我想传递的任何记录时 order_id 然后将用户重定向到该特定订单详细信息屏幕。
编辑
查看
<odoo>
<data>
<record id="amgl_dashboard_tree" model="ir.ui.view">
<field name="name">Dashboard</field>
<field name="model">amgl.dashboard</field>
<field name="arch" type="xml">
<tree default_order="state desc" decoration-bf ="state in ('expecting','pending','completed')" decoration-info="state=='expecting'" decoration-danger="state=='pending'" decoration-succes="state=='completed'" string="Dashboard" create="false" edit="false">
<field name="order_id" invisible="1"/>
<button name="view_record" type="object" string="View Record" custom="click" class="oe_highlight"/>
<field name="first_name"/>
<field name="last_name"/>
<field name="account_number"/>
<field name="product"/>
<field name="quantity"/>
<field name="total_weight"/>
<field name="state"/>
</tree>
</field>
</record>
</data>
</odoo>
.py
class Dashboard(models.Model):
_name = 'amgl.dashboard'
_auto = False
@api.multi
def view_record(self):
print self
@api.model_cr
def init(self):
tools.drop_view_if_exists(self._cr, 'dashboard')
self._cr.execute("""
CREATE or REPLACE VIEW amgl_dashboard AS (
SELECT
row_number() OVER () AS id,
c.name AS first_name,
c.last_name AS last_name,
c.account_type AS account_type,
c.account_number AS account_number,
(select name from amgl_products where id = ol.products) AS product,
ol.quantity AS quantity,
(CASE
WHEN (select weight_unit from amgl_products where id = ol.products) = 'oz'
THEN
(select weight_per_piece from public.amgl_products where id = ol.products) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'gram'
THEN
((select weight_per_piece from public.amgl_products where id = ol.products) / 28.34952) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'pounds'
THEN
((select weight_per_piece from amgl_products where id = ol.products) * 16) * ol.quantity
WHEN (select weight_unit from amgl_products where id = ol.products) = 'kg'
THEN
((select weight_per_piece from amgl_products where id = ol.products) / 0.02834952) * ol.quantity
ELSE 0.0
END) AS total_weight,
o.state AS state,
o.id AS order_id
FROM amgl_order AS o
INNER JOIN amgl_customer AS c ON c.id = o.customer_id
INNER JOIN amgl_order_line AS ol ON ol.order_id = o.id
)""")
name = fields.Char()
first_name = fields.Char(string="First Name")
last_name = fields.Char(string="Last Name")
account_type = fields.Char(string="Account Type")
account_number = fields.Char(string="Account Number")
product = fields.Char(string="Product")
quantity = fields.Float(string="Quantity")
total_weight = fields.Float(string="Total Weight")
state = fields.Selection([('expecting', 'Expecting'), ('pending', 'Pending'),
('completed', 'Completed'), ('waiting', 'Waiting For Approval')],
'Status', default='expecting')
order_id = fields.Integer(string="Order Id")
动作
<record id="amgl.dashboard_action_window" model="ir.actions.act_window">
<field name="name">Dashboard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">amgl.dashboard</field>
<field name="view_mode">tree</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
<!-- Add Text Here -->
</p><p>
<!-- More details about what a user can do with this object will be OK -->
</p>
</field>
</record>
调试器
Self._context
Self
当您单击 listview
上的记录时,会执行一个操作,将您从 listview
移至 `formview。
默认操作始终存在,但如果您想传递一些额外参数,则必须定义您自己的参数。有关具体示例,请查看 sale.action_quotations
操作。此操作将用户从视图 1 移动到视图 2(例如列表到表单)
https://github.com/OCA/OCB/blob/10.0/addons/sale/views/sale_views.xml#L518
<record id="action_quotations" model="ir.actions.act_window">
...
<field name="context">{'hide_sale': True}</field>
...
</record
此操作负责在视图之间移动报价单中的用户。查看上下文是如何传递的。你只需要在 view_mode
上 tree,form
即可。
我认为有几种方法可以可能起作用。我不是 100% 肯定他们中的任何一个,但我会给你一般的想法。
XML唯一的解决方案
George 的主要想法是正确的 - 您需要创建一个操作来管理您想要做的事情。
重要的区别在于您似乎希望列表视图显示一个模型 (amgl.dashboard
) 而表单视图显示另一个模型 (sale.order
)
通常,我建议您创建一个 button
并将其显示在列表视图中,以便将用户直接带到销售订单表单。但是,您也可以在 src_model
的帮助下使用标准 act_window
操作。
核心示例:
Odoo 使用下面的按钮调用操作,这导致用户能够转到 stock.location
表单视图并转到 product.product
列表。您本质上是想在没有按钮的情况下使用不同的模型来执行与此相反的操作。
<button string="Products"
class="oe_stat_button"
icon="fa-filter" name="%(act_product_location_open)d" type="action"
context="{'location_id': active_id}"
/>
<act_window
id="act_product_location_open"
name="Products"
src_model="stock.location"
res_model="product.product"
context="{'location': active_id,
'search_default_real_stock_available': 1,
'search_default_virtual_stock_available': 1,
'search_default_virtual_stock_negative': 1,
'search_default_real_stock_negative': 1}"/>
Python 解法:
假设您的 view_record
方法已经被调用,您可以直接从方法本身 return "View Sales Order form" 操作。
# Make sure these imports are called in your file
# If you are on Odoo 9 or earlier, you must use openerp instead of odoo
from odoo import _
from odoo.exceptions import ValidationError
class Dashboard(models.Model):
_name = 'amgl.dashboard'
_auto = False
@api.multi
def view_record(self):
"""Return a Window Action to view the Sales Order form"""
self.ensure_one()
action = self.env.ref('sale.action_orders')
form = self.env.ref('sale.view_order_form', False)
if not (action or form):
raise ValidationError(_("Sales Orders Action or Form not found!"))
return {
'name': action.name,
'help': action.help,
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'views': [(form_id.id, 'form')]
'res_model': action.res_model,
'res_id': self._context.get('id'),
'target': 'current',
'context': {},
}