5

odoo 开发入门教程系列-准备一些操作(Action)? - 授客

 1 year ago
source link: https://www.cnblogs.com/shouke/p/17253371.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

准备一些操作(Action)?

到目前为止,我们主要通过声明字段和视图来构建模块。在任何真实的业务场景中,我们都希望将一些业务逻辑链接到操作按钮。在我们的房地产示例中,我们希望能够:

  • 取消或将房产设置为已售出
  • 接受或拒绝报价

有人可能会说,我们已经可以通过手动更改状态来完成这些事情,但这并不太方便。此外,我们还想增加一些额外的处理:当报价被接受时,我们想设定房产的售价和买家。

操作类型(Action Type)

参考:本主题相关文档可参考ActionsError management

在我们的房地产模块中,我们希望将些业务逻辑和一些按钮关联,最常见的做法是:

  • 在视图中添加一个按钮,比如在视图header部分:
<form>
    <header>
        <button name="action_do_something" type="object" string="Do Something"/>
    </header>
    <sheet>
        <field name="name"/>
    </sheet>
</form>
  • 将该按钮和业务逻辑关联:
from odoo import fields, models

class TestAction(models.Model):
    _name = "test.action"

    name = fields.Char()

    def action_do_something(self):
        for record in self:
            record.name = "Something"
        return True

通过将type="object"分配给我们的按钮, Odoo框架将在给定模型上执行带有name="action_do_something"的Python方法。

需要注意的第一个重要细节是,我们的方法名没有前缀下划线(_)。这使我们的方法成为一个公共方法,可以直接通过Odoo接口调用(通过RPC调用)。到目前为止,我们创建的所有方法(compute、onchange)都是在内部调用的,因此我们使用了前缀为下划线的私有方法。除非需要从用户界面调用方法,否则应始终将方法定义为私有。

还要注意,我们对self循环。始终假设可以对多个记录调用同一个方法;这有利于重用性。

最后,公共方法应该始终返回一些东西,以便可以通过XML-RPC调用它。当有疑问时,只需return True即可。

Odoo源代码中有数百个示例。其中一个例子是 视图中的按钮 和其对应的Python方法

<form class="o_lead_opportunity_form" js_class="crm_form">
    <header>
        <button name="action_set_won_rainbowman" string="Mark Won"
            type="object" class="oe_highlight"
            attrs="{'invisible': ['|','|', ('active','=',False), ('probability', '=', 100), ('type', '=', 'lead')]}"/>
        ...略
    def action_set_won_rainbowman(self):
        self.ensure_one()
        self.action_set_won()

        message = self._get_rainbowman_message()
        if message:
            return {
                'effect': {
                    'fadeout': 'slow',
                    'message': message,
                    'img_url': '/web/image/%s/%s/image_1024' % (self.team_id.user_id._name, self.team_id.user_id.id) if self.team_id.user_id.image_1024 else '/web/static/src/img/smile.svg',
                    'type': 'rainbow_man',
                }
            }
        return True

添加 ‘Cancel’ 和‘Sold’ 按钮到 estate.property 模型。已取消的房产不能被设置为已出售,已出售的房产不能被取消。

预期效果动画:

1569452-20230324210935350-2026001039.gif
1569452-20230324210954676-1238345899.gif

提示:为了抛出错误,可以使用 UserError 函数。

修改odoo14\custom\estate\views\estate_property_views.xml中的estate_property_view_form视图

    <record id="estate_property_view_form" model="ir.ui.view">
        <field name="name">estate.property.form</field>
        <field name="model">estate.property</field>
        <field name="arch" type="xml">
            <form string="estate property form">
                <!-- header元素为本次新增 -->
                <header>
                    <button name="set_property_sold" type="object" string="SOLD"></button>                    
                    <button name="set_property_canceled" type="object" string="CANCEL"></button>
                </header>
                <sheet>
                    <h1>
                        <field name="name"/>
                    </h1>
                    <p>
                        <field name="tag_ids" widget="many2many_tags"/>
                    </p>
                    <group>
                        <group>
                            <!-- state 字段为本次新增 -->
                            <field name="state" string="Status"></field>
                            <field name="property_type_id" string="Property Type"></field>
                            <field name="postcode" string="Postcode" ></field>
                            <field name="date_availability" string="Available From"></field>
                        </group>
                        <group>
                            <field name="expected_price" string="Expected Price"></field>
                            <field name="best_price" string="Best Price" />
                            <field name="selling_price" string="Selling Price"></field>
                        </group>
                    </group>
                    <notebook>
                        <page string="Description">
                            <group>
                                <field name="description"></field>
                                <field name="bedrooms"></field>
                                <field name="living_area"></field>
                                <field name="facades"></field>
                                <field name="garage"></field>
                                <field name="garden"></field>
                                <field name="garden_area"></field>
                                <field name="garden_orientation"></field>
                                <field name="total_area" string="Total Area"></field>
                            </group>
                        </page>
                        <page string="Offers">
                            <field name="offer_ids" />
                        </page>
                        <page string="Other info">
                            <group>
                                <field name="salesman_id" string="Salesman"></field>
                                <field name="buyer_id" string="Buyer"></field>
                            </group>
                        </page>
                    </notebook>
                </sheet>
            </form>
        </field>
    </record>

修改odoo14\custom\estate\models\estate_property.py

开头增加导入UserError

from odoo.exceptions import UserError

末尾新增以下代码

    def set_property_canceled(self):
        if self.state == 'Sold':
            raise UserError('不能取消已出售房产')
        else:
            self.state = 'Canceled'

        return True

    def set_property_sold(self):
        if self.state == 'Canceled':
            raise UserError('不能出售已取消房产')
        else:
            self.state = 'Sold'

        return True

重启服务,浏览器中验证

添加‘Accept’ 和‘Refuse’ 到estate.property.offer 模型。

预期效果动画:

1569452-20230324211018162-85789158.gif
1569452-20230324211040371-1603410142.gif

提示: 把图标当按钮用,请查看这个例子

<button name="action_confirm" string="Confirm" states="draft" type="object" icon="fa-check"/>

修改odoo14\custom\estate\views\estate_property_offer_views.xmlestate_property_offer_view_tree

    <record id="estate_property_offer_view_tree" model="ir.ui.view">
        <field name="name">estate.property.offer.tree</field>
        <field name="model">estate.property.offer</field>
        <field name="arch" type="xml">
            <tree string="PropertyOffers">
                <field name="price" string="Price"/>
                <field name="partner_id" string="partner ID"/>
                <field name="validity" string="Validity(days)"/>
                <field name="deadline" string="Deadline"/>
                <!-- button 为本次新增 -->
                <button name="action_accept_offer" string=""  type="object" icon="fa-check"/>
                <button name="action_refuse_offer" string=""  type="object" icon="fa-times"/>
                <field name="status" string="Status"/>
            </tree>
        </field>
    </record>

修改odoo14\custom\estate\models\estate_property_offer.py,最末尾添加以下代码

    def action_accept_offer(self):
        self.status = 'Accepted'
        self.property_id.state = 'Offer Accepted'
        return True

    def action_refuse_offer(self):
        self.status = 'Refused'
        return True

重启服务,浏览器中验证

1569452-20230324211106242-199764773.png

当报价被接受时,设定相应房产的买家和售价。

预期效果动画:

1569452-20230324211132974-36167678.gif

注意:在现实生活中,给定房产只能接受一个报价!

修改odoo14\custom\estate\models\estate_property_offer.pyaction_accept_offer函数如下

    def action_accept_offer(self):
        self.status = 'Accepted'
        self.property_id.state = 'Offer Accepted'
        self.property_id.selling_price = 260000
        self.property_id.buyer_id = self.partner_id
        return True

重启服务,浏览器中验证

对象类型(Object Type)

“一些用户界面”章节中,我们创建了连接到菜单的操作。你可能好奇,是否可以连接操作到按钮。好消息,的确可以,其中一种实现方式如下:

<button type="action" name="%(test.test_model_action)d" string="My Action"/>

我们使用 type="action" 且在name中引用外部标识


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK