Odoo | Module | 统计系统周期使用人数/当前在线人数

文内材料

GITHUB地址

前言介绍

Odoo作为开源ERP系统No.01,近年愈发的得到国内很多公司的关注。

虽然它的定位是中小型企业的ERP管理系统,但是在几年的Odoo开发实施过程中,有不足50人的小型企业,也有上万人的中大型企业。功能快速落地高度个性化扩展是它的核心特性,使用其他框架开发一个完整的页面可能需要1-2天,但在Odoo可能远超你的预期,在同等页面且不做翻译的前提下,成熟的Odoo开发工程师只需要 <0.5天的时间即可完成界面的主体开发(不包含各类赋值、处理逻辑)。

所以如果有ERP需求但是不想花费太多License费用的用户或者组织可以了解了解:Odoo

需求描述

返回正题,我们经常看见政府门户类网站或者一些访问量很大的公共网站,都会有一个当前在线人数的功能。

回到Odoo,原生并没有提供这样的数据统计方式或者功能,但是不要担心,毕竟Odoo是一个扩展十分方便的框架,我们可以通过现有的一些功能进行集成。

对于Odoo来说,有三种情况:

  1. 初次登录
  2. Session未过期,通过历史URL进入系统(无需登录)
  3. 网页打开但长时间未处理

源码阅读

  • 初次登录、Session未过期访问

    对于登录和已登录状态访问来说,如果验证成功会重定向回/web的route进行处理,并且最终会进入try内容,如果不发生错误,那么应该返回的是正常的网页内容+返回状态码200

    python 复制代码
    @http.route('/web', type='http', auth="none")
    def web_client(self, s_action=None, **kw):
        ensure_db()
        if not request.session.uid:
            return werkzeug.utils.redirect('/web/login', 303)
        if kw.get('redirect'):
            return werkzeug.utils.redirect(kw.get('redirect'), 303)
    
        request.uid = request.session.uid
        try:
            context = request.env['ir.http'].webclient_rendering_context()
            response = request.render('web.webclient_bootstrap', qcontext=context)
            response.headers['X-Frame-Options'] = 'DENY'
            return response
        except AccessError:
            return werkzeug.utils.redirect('/web/login?error=access')
  • 网页打开但长时间未处理

    初次登录、已登录访问可以通过web_client的扩展进行用户信息记录,但是如何检测用户还在使用网页,而不是使用完就关闭页面,也就是如何检测用户的在线情况:Longpolling

    我们可以通过新创建一个Module继承mail模块,以激活longpolling的定时轮询功能,轮询功能将定期的与服务器进行信息交互(交互方法如下),我们后续可以对其进行扩展:

    python 复制代码
    @route('/longpolling/poll', type="json", auth="public")
    def poll(self, channels, last, options=None):
        if options is None:
            options = {}
        if not dispatch:
            raise Exception("bus.Bus unavailable")
        if [c for c in channels if not isinstance(c, pycompat.string_types)]:
            raise Exception("bus.Bus only string channels are allowed.")
        if request.registry.in_test_mode():
            raise exceptions.UserError(_("bus.Bus not available in test mode"))
        return self._poll(request.db, channels, last, options)

集成操作

  • 操作内容
    1. 创建新模块,模块继承mail
    2. 集成登录controller、poll
    3. 提供用户访问信息记录表,必要时提供界面显示
  1. 创建新模块,继承mail

  2. 集成登录controller、poll

    python 复制代码
    # -*- coding: utf-8 -*-
    
    import odoo
    from odoo import http
    from odoo.http import request
    from odoo import exceptions, _
    from odoo.http import content_disposition, dispatch_rpc, request, \
        serialize_exception as _serialize_exception, route, Response
    from odoo.addons.bus.controllers.main import BusController
    from odoo.addons.web.controllers.main import Home
    
    
    class BusControllerInherit(BusController):
        # 存活检测 longpolling
        @route()
        def poll(self, channels, last, options=None):
            self.collection_current_users()
            res = super(BusControllerInherit, self).poll(channels, last, options)
            return res
        @staticmethod
        def collection_current_users():
            request_ip = request.httprequest.remote_addr
            request_db = request.httprequest.session.db
            request_user = request.httprequest.session.uid
            request_login = request.httprequest.session.login
    
            try:
                conn = odoo.sql_db.db_connect(request_db)
                with conn.cursor() as cr:
                    sql = """
                        insert into collection_user_info(request_ip, request_db, request_user, request_login, fast_login_time, latest_login_time)
                        values (%s, %s, %s, %s, now(), now())
                        on conflict (request_ip, request_db, request_user, request_login) do update set latest_login_time = now();
                    """
                    cr.execute(sql, (request_ip, request_db, request_user, request_login))
            except Exception as e:
                raise e
    
    class HomeInherit(Home):
        # 记录登录或者session存在时自动登录的情况
        @http.route()
        def web_client(self, s_action=None, **kw):
            res = super(HomeInherit, self).web_client(s_action, **kw)
            if isinstance(res, Response) and res.status_code == 200:
                BusControllerInherit.collection_current_users()
            return res
  3. 提供用户访问信息记录表,必要时提供界面显示

    具体代码不展示了,直接放图吧,因为局域网的关系,访问数据不是很多,大家可以自行下载模块安装测试 GITHUB工程地址

🎉如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了🎉

【点赞】⭐️⭐️⭐️⭐️⭐️

【关注】⭐️⭐️⭐️⭐️⭐️

【收藏】⭐️⭐️⭐️⭐️⭐️

Thanks for watching.

--Kenny

相关推荐
odoo中国3 天前
Odoo 19技术教程 : 如何在 Odoo 19 中创建 Many2one 组件
开发语言·odoo·odoo19·odoo技术·many2one
Mr.E57 天前
odoo18 关闭搜索框点击自动弹出下拉框
开发语言·前端·javascript·odoo·owl·odoo18
odoo中国14 天前
Odoo 19 技术教程:如何在 Odoo 19 中使用模型属性
odoo·odoo开发·odoo19·模型属性
odoo中国15 天前
Odoo 19 制造模块功能:制造模块中废品管理操作指南
制造·odoo·odoo19·生产废品管理·生产报废管理·报废流程
odoo中国16 天前
Odoo 19 中升级(迁移)脚本的使用方法
odoo·odoo19·odoo技术·升级脚本·迁移脚本
odoo中国17 天前
Odoo 19 安全完整解析:多层防护守护企业核心数据
安全·odoo·数据备份·数据保护·用户权限·odoo19·用户访问规则
odoo中国19 天前
Odoo 19 功能性报表解析:如何高效使用补货报表
odoo·odoo19·库存报表·补货报表
odoo中国19 天前
如何在 Odoo 19 中创建序列
odoo·odoo19·自定义单据序列
odoo中国1 个月前
Odoo 19 财务功能概述:财务模块中的定期存货计价(期末库存结转)
odoo·库存管理·财务管理·odoo19·库存计价·库存估值·期末库存结转
odoo中国1 个月前
Odoo 19 库存功能实操:产品包装的设置与管理
odoo·仓库管理·odoo19·包装设置与管理