Odoo16定时任务自动触发调用http.request.session报错object unbound
Odoo定时任务调用session对象报错问题解决
问题描述
在Odoo中配置定时任务调用session对象时,出现以下差异表现:
- 手动点击定时任务的执行按钮时,任务可成功运行
- 定时任务自动触发时,抛出错误:
ValueError: <class 'RuntimeError'>: "object unbound" while evaluating
相关配置与代码如下:
XML定时任务配置
<odoo noupdate="1"> <record id="cron_check_timeout_session" model="ir.cron"> <field name="name">Check expired sessions</field> <field name="user_id" ref="base.user_admin"/> <field name="interval_number">1</field> <field name="interval_type">minutes</field> <field name="numbercall">-1</field> <field name="nextcall" eval="datetime.now().replace(hour=0, minute=0, second=0)"/> <field name="model_id" ref="hr_zk_attendance.model_zk_machine"/> <field name="state">code</field> <field name="code">model.check_session_timeout()</field> </record> </odoo>
Python方法代码
@api.model def check_session_timeout(self): cookies = http.request.session _logger.info(f"\x1b[32;21m{cookies}")
问题原因
定时任务自动触发时,是在后台异步执行的,不存在HTTP请求上下文:
http.request仅在用户通过浏览器发起HTTP请求时才会绑定到当前请求,手动执行定时任务时,是在当前登录用户的请求上下文环境中运行,因此可以正常获取http.request.session- 自动触发的定时任务脱离了HTTP请求环境,
http.request处于未绑定状态,直接调用会触发"object unbound"错误
解决方案
避免在定时任务中直接依赖http.request,改用Odoo内置的会话管理方式:
方案1:通过session_store直接操作会话
from odoo import models, api, _logger from odoo.http import session_store class ZkMachine(models.Model): _inherit = 'zk.machine' @api.model def check_session_timeout(self): # 获取所有活跃会话 all_sessions = session_store.list() for session in all_sessions: # 按需处理会话,比如检查过期时间 _logger.info(f"\x1b[32;21m会话ID: {session.sid}, 过期时间: {session.expire}")
方案2:使用ir.session模型(Odoo 13及以上版本支持)
Odoo 13+提供了ir.session模型来管理用户会话,可以直接通过ORM查询:
from odoo import models, api, _logger, fields class ZkMachine(models.Model): _inherit = 'zk.machine' @api.model def check_session_timeout(self): # 查询所有会话记录 session_records = self.env['ir.session'].search([]) for session in session_records: _logger.info(f"\x1b[32;21m用户: {session.login}, 会话ID: {session.session_id}, 过期时间: {session.expire}") # 可选:过滤并处理已过期的会话 expired_sessions = self.env['ir.session'].search([('expire', '<=', fields.Datetime.now())]) if expired_sessions: _logger.info(f"\x1b[32;21m已过期会话数量: {len(expired_sessions)}") # 可根据需求清理过期会话 # expired_sessions.unlink()
内容的提问来源于stack exchange,提问作者ricardo chirinos
相关产品推荐
相关产品推荐

