You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Odoo技术问询:取消/离开表单时如何删除已保存模型?

解决Odoo预约表单自动保存后取消/离开时删除记录的方案

嘿,这个场景我太熟悉了——Odoo的表单机制确实会在触发某些按钮动作时自动保存记录,哪怕用户只是想查个时段还没确定要预约。下面给你几个实用的解决思路,结合前端和后端逻辑,覆盖用户点击取消和直接关闭页面的情况:

1. 前端监听取消按钮+页面离开事件,主动删除记录

这是最直接的方式,针对用户明确点击“取消”或者直接关闭页面的情况,通过JavaScript调用Odoo的RPC接口删除当前记录。

步骤1:在表单视图中添加按钮和脚本

修改你的预约模型的form视图,添加取消按钮和自定义脚本:

<field name="arch" type="xml">
    <form>
        <!-- 你的预约表单字段,比如姓名、联系方式等 -->
        <button name="action_check_availability" string="查询可用时段" type="object" class="btn-primary"/>
        <button name="action_cancel_reservation" string="取消" type="object" class="btn-secondary"/>
        
        <script type="text/javascript">
            document.addEventListener('DOMContentLoaded', function() {
                // 获取当前记录的ID(Odoo保存后会生成这个ID)
                const recordId = odoo.__DEBUG__.models[0].res_id;
                
                // 监听取消按钮点击事件
                const cancelBtn = document.querySelector('.btn-secondary[name="action_cancel_reservation"]');
                if (cancelBtn) {
                    cancelBtn.addEventListener('click', function(e) {
                        if (recordId) {
                            // 调用后端unlink方法删除记录
                            odoo.rpc({
                                model: 'your.reservation.model', // 替换成你的模型名
                                method: 'unlink',
                                args: [[recordId]],
                            }).then(() => {
                                // 关闭表单或跳转到列表页
                                window.location.href = '/web#action=your_reservation_action_id'; // 替换成你的动作ID
                            });
                        }
                    });
                }
                
                // 监听页面离开事件(比如用户直接关闭标签页)
                window.addEventListener('beforeunload', function(e) {
                    if (recordId) {
                        // 用同步RPC确保删除请求能执行完成
                        odoo.rpc({
                            model: 'your.reservation.model',
                            method: 'unlink',
                            args: [[recordId]],
                        }, {async: false});
                    }
                });
            });
        </script>
    </form>
</field>

步骤2:后端实现取消动作(可选)

你也可以直接在后端的取消按钮方法里处理删除,这样更符合Odoo的逻辑:

from odoo import models, fields

class YourReservationModel(models.Model):
    _name = 'your.reservation.model'
    _description = '预约记录'
    
    # 你的字段定义
    name = fields.Char('姓名')
    phone = fields.Char('手机号')
    # ...其他字段
    
    def action_check_availability(self):
        # 你的查询可用时段逻辑,比如返回通知或更新字段
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': '可用时段查询结果',
                'message': '上午9:00、下午2:00有空',
                'sticky': False,
            }
        }
    
    def action_cancel_reservation(self):
        # 删除当前记录
        self.unlink()
        # 关闭表单
        return {
            'type': 'ir.actions.act_window_close',
        }

2. 后端定时任务兜底,清理未完成的草稿预约

有些用户可能直接关闭页面,前端的beforeunload事件可能因为浏览器限制没触发,这时候就需要后端定时任务来清理“废弃”的预约记录。

步骤1:给模型添加标记字段

给你的预约模型加一个草稿标记和创建时间字段:

from odoo import models, fields
from datetime import timedelta

class YourReservationModel(models.Model):
    _name = 'your.reservation.model'
    
    is_draft_reservation = fields.Boolean('草稿预约', default=True)
    create_date = fields.Datetime('创建时间', default=fields.Datetime.now)
    
    # ...其他字段和方法
    
    def _cleanup_draft_reservations(self):
        # 清理创建超过10分钟的草稿预约(可根据需求调整时长)
        cutoff_time = fields.Datetime.now() - timedelta(minutes=10)
        draft_records = self.search([
            ('is_draft_reservation', '=', True),
            ('create_date', '<=', cutoff_time)
        ])
        draft_records.unlink()

步骤2:配置定时任务

在模块的data目录下创建ir_cron.xml文件,添加定时任务:

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="cron_cleanup_draft_reservations" model="ir.cron">
        <field name="name">清理未完成的草稿预约</field>
        <field name="model_id" ref="model_your_reservation_model"/> <!-- 替换成你的模型引用 -->
        <field name="state">code</field>
        <field name="code">model._cleanup_draft_reservations()</field>
        <field name="interval_number">10</field> <!-- 每10分钟执行一次 -->
        <field name="interval_type">minutes</field>
        <field name="numbercall">-1</field> <!-- 无限次执行 -->
        <field name="active" eval="True"/>
    </record>
</odoo>

记得在模块的__manifest__.py里把这个xml文件加到data列表中。

步骤3:用户完成预约时标记为非草稿

当用户确认预约(比如点击“提交预约”按钮)时,把is_draft_reservation设为False,这样定时任务就不会删除这条有效记录:

def action_confirm_reservation(self):
    self.write({'is_draft_reservation': False})
    # 其他确认逻辑,比如发送通知等

注意事项

  • 前端的beforeunload事件中使用同步RPC是为了确保删除请求能在页面关闭前执行,但有些现代浏览器可能会限制同步请求,所以后端定时任务是必要的兜底方案。
  • 如果你的表单是在弹窗中打开的,可能需要调整前端脚本的记录ID获取方式,比如通过Odoo的web.FormController来获取当前记录。

内容的提问来源于stack exchange,提问作者Marcio Cruz

火山引擎 最新活动