Session

本章基于Odoo18.0

OWL中的Session

我们先来看OWL的session代码的定义:

export const session = odoo.__session_info__ || {};
delete odoo.__session_info__;

这是session.js中的全部代码,看起来极其简单。 先定义了一个session的常量,然后删除了odoo.session_info这个中间变量。

那么这个odoo.session_info又是在哪里定义的呢?

<template id="web.webclient_bootstrap">
    <t t-call="web.layout">
        <t t-set="head_web">
            <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
            <meta name="theme-color" content="#71639e"/>
            <link rel="manifest" href="/web/manifest.webmanifest" crossorigin="use-credentials"/>
            <link rel="apple-touch-icon" href="/web/static/img/odoo-icon-ios.png"/>
            <script type="text/javascript">
                // Block to avoid leaking variables in the script scope
                {
                    odoo.__session_info__ = <t t-out="json.dumps(session_info)"/>;
                    const { user_context,  cache_hashes } = odoo.__session_info__;
                    const lang = new URLSearchParams(document.location.search).get("lang");
                    let menuURL = `/web/webclient/load_menus/${cache_hashes.load_menus}`;
                    if (lang) {
                        user_context.lang = lang;
                        menuURL += `?lang=${lang}`
                    }
                    odoo.reloadMenus = () => fetch(menuURL).then(res => res.json());
                    odoo.loadMenusPromise = odoo.reloadMenus();
                    // Prefetch translations to speedup webclient. This is done in JS because link rel="prefetch"
                    // is not yet supported on safari.
                    fetch(`/web/webclient/translations/${cache_hashes.translations}?lang=${user_context.lang}`);
                }
            </script>
            <t t-call-assets="web.assets_web_print" media="print" t-js="false"/>

            <t t-if="request.cookies.get('color_scheme') == 'dark'">
                <t t-call-assets="web.assets_web_dark" media="screen"/>
            </t>
            <t t-else="">
                <t t-call-assets="web.assets_web" media="screen"/>
            </t>
            <t t-call="web.conditional_assets_tests" media="screen"/>
        </t>
        <t t-set="head" t-value="head_web + (head or '')" media="screen"/>
        <t t-set="body_classname" t-value="'o_web_client'"/>
    </t>
</template>

我们在WC的视图代码中找到了session_info的定义。我们看到session_info是通过json.dumps()方法从session_info这个变量中出来的。那么我们下一步就要找到session_info这个变量是如何而来的了。

对于Backend来说,是由控制器在调用 request.render() 时放进渲染上下文:

from odoo import http
from odoo.http import request

class WebClient(http.Controller):

    @http.route('/web', type='http', auth='user')
    def web_client(self, **kw):
        session_info = request.env['ir.http'].get_webclient_session_info()
        # 这里把 session_info 作为变量传给模板
        return request.render('web.webclient_bootstrap', {
            'session_info': session_info,
            'debug': request.debug,
            # 其他上下文字段...
        })

对于fronted来说,则是由前端页面直接调用:

<script type="text/javascript">
    odoo.__session_info__ = <t t-out="json.dumps(request.env['ir.http'].get_frontend_session_info())"/>;
</script>

ir.http模型内部:

class IrHttp(models.AbstractModel):
    _name = 'ir.http'

    def get_webclient_session_info(self):
        # 返回后台需要的完整 session 信息
        return {
            'user_context': request.context,
            'cache_hashes': self._get_asset_hashes(),
            # 还有 uid, user_company, companies 等字段
        }

    def get_frontend_session_info(self):
        # 返回前端(门户)精简版 session 信息
        return {
            'user_context': request.context,
            'cache_hashes': self._get_asset_hashes(),
            # 精简字段集合
        }

因此,如果我们想要通过后台给前端session_info中传入额外的变量,则需要继承ir.http模型的相应的方法完成。

results matching ""

    No results matching ""