You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:05:18