odoo17核心概念view2——view_service

2023-12-27 03:01

本文主要是介绍odoo17核心概念view2——view_service,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这是view系列的第二篇文章,介绍view_service.js
static\src\views\view_service.js

一、前端js

/** @odoo-module **/import { registry } from "@web/core/registry";
import { UPDATE_METHODS } from "@web/core/orm_service";export const viewService = {dependencies: ["orm"],start(env, { orm }) {let cache = {};function clearCache() {cache = {};const processedArchs = registry.category("__processed_archs__");processedArchs.content = {};processedArchs.trigger("UPDATE");}env.bus.addEventListener("CLEAR-CACHES", clearCache);env.bus.addEventListener("RPC:RESPONSE", (ev) => {const { model, method } = ev.detail.data.params;if (["ir.ui.view", "ir.filters"].includes(model)) {if (UPDATE_METHODS.includes(method)) {clearCache();}}});/*** Loads various information concerning views: fields_view for each view,* fields of the corresponding model, and optionally the filters.** @param {LoadViewsParams} params* @param {LoadViewsOptions} [options={}]* @returns {Promise<ViewDescriptions>}*/async function loadViews(params, options = {}) {const { context, resModel, views } = params;const loadViewsOptions = {action_id: options.actionId || false,load_filters: options.loadIrFilters || false,toolbar: (!context?.disable_toolbar && options.loadActionMenus) || false,};for (const key in options) {if (!["actionId", "loadIrFilters", "loadActionMenus"].includes(key)) {loadViewsOptions[key] = options[key];}}if (env.isSmall) {loadViewsOptions.mobile = true;}const filteredContext = Object.fromEntries(Object.entries(context || {}).filter(([k, v]) => k == "lang" || k.endsWith("_view_ref")));const key = JSON.stringify([resModel, views, filteredContext, loadViewsOptions]);if (!cache[key]) {debuggercache[key] = orm.call(resModel, "get_views", [], {context: filteredContext,views,options: loadViewsOptions,}).then((result) => {const { models, views } = result;const viewDescriptions = {fields: models[resModel],relatedModels: models,views: {},};for (const viewType in views) {const { arch, toolbar, id, filters, custom_view_id } = views[viewType];const viewDescription = { arch, id, custom_view_id };if (toolbar) {viewDescription.actionMenus = toolbar;}if (filters) {viewDescription.irFilters = filters;}viewDescriptions.views[viewType] = viewDescription;}return viewDescriptions;}).catch((error) => {delete cache[key];return Promise.reject(error);});}return cache[key];}return { loadViews };},
};registry.category("services").add("view", viewService);

1 、服务开头提供了一个清理缓存的函数clearCache, 将注册表中的registry.category(“processed_archs”)清空,并且触发它的update事件。
2、后面就是最重要的loadViews函数了,加载有关视图的各种信息:每个视图的字段视图,对应模型的字段,以及可选的过滤器。
输入参数params: 包含了上下文信息,模型,视图 ,举个例子:

context:{params:{action:201,cids:1,menu_id:124,model:'crax_demo.crax.demo',view_type:'list'}}
resModel:crax_demo.crax.demo
views:[[false,'list'],[false,'form'],[false,'search']]

输入参数option:是一个字典

actionid
loadActionMenus:true
LoadIrFilters:true

这一段代码是对传入的参数进行结构赋值,并且组装传入的option到loadViewsOptions ,同时组装filteredContext

  const { context, resModel, views } = params;const loadViewsOptions = {action_id: options.actionId || false,load_filters: options.loadIrFilters || false,toolbar: (!context?.disable_toolbar && options.loadActionMenus) || false,};for (const key in options) {if (!["actionId", "loadIrFilters", "loadActionMenus"].includes(key)) {loadViewsOptions[key] = options[key];}}if (env.isSmall) {loadViewsOptions.mobile = true;}const filteredContext = Object.fromEntries(Object.entries(context || {}).filter(([k, v]) => k == "lang" || k.endsWith("_view_ref")));

然后将这些变量转换成字符串

const key = JSON.stringify([resModel, views, filteredContext, loadViewsOptions]);

判断缓存中是否有这个key,如果有,则从缓存中返回,否则调用orm从后端获取

cache[key] = orm.call(resModel, "get_views", [], {context: filteredContext,views,options: loadViewsOptions,}).then((result) => {const { models, views } = result;const viewDescriptions = {fields: models[resModel],relatedModels: models,views: {},};for (const viewType in views) {const { arch, toolbar, id, filters, custom_view_id } = views[viewType];const viewDescription = { arch, id, custom_view_id };if (toolbar) {viewDescription.actionMenus = toolbar;}if (filters) {viewDescription.irFilters = filters;}viewDescriptions.views[viewType] = viewDescription;}return viewDescriptions;}).catch((error) => {delete cache[key];return Promise.reject(error);});

orm是一个promise,返回值直接付给了缓存, 后面统一返回缓存中的值。
call, then ,catch 这是promise标准的写法。

.call(resModel, "get_views", [], {context: filteredContext,views,options: loadViewsOptions,})

任何一个模型都有一个get_views方法,这是继承自它的父类 base,具体的实现是在base模块的ir_ui_view中
odoo\addons\base\models\ir_ui_view.py

@api.modeldef get_views(self, views, options=None):""" Returns the fields_views of given views, along with the fields ofthe current model, and optionally its filters for the given action.The return of the method can only depend on the requested view types,access rights (views or other records), view access rules, options,context lang and TYPE_view_ref (other context values cannot be used).Python expressions contained in views or representing domains (onpython fields) will be evaluated by the client with all the contextvalues as well as the record values it has.:param views: list of [view_id, view_type]:param dict options: a dict optional boolean flags, set to enable:``toolbar``includes contextual actions when loading fields_views``load_filters``returns the model's filters``action_id``id of the action to get the filters, otherwise loads the globalfilters or the model:return: dictionary with fields_views, fields and optionally filters"""省略100行。。。。return result

views: views:[[false,‘list’],[false,‘form’],[false,‘search’]]
options: actionid 等

返回值:
views : 各种类型view的id 和arch 以及其他信息
models: 模型的字段信息

.then((result) => {const { models, views } = result;const viewDescriptions = {fields: models[resModel],relatedModels: models,views: {},};for (const viewType in views) {const { arch, toolbar, id, filters, custom_view_id } = views[viewType];const viewDescription = { arch, id, custom_view_id };if (toolbar) {viewDescription.actionMenus = toolbar;}if (filters) {viewDescription.irFilters = filters;}viewDescriptions.views[viewType] = viewDescription;}return viewDescriptions;

这一段是根据orm的返回值 组装viewDescriptions 字段,并返回,这个字段包含了:

                    fields: models[resModel],relatedModels: models,views: {},

这里有个关键点 relatedModels, 通过debug可以看到,这是一个模型的所有的字段信息。是视图的显示中,它起到了驱动的作用。 关于这一点,后面再细聊。
后面的for循环是为了填充views这个字段,对于每种类型的视图,都包含了arch,id,custom_view_id等字段。

总结一波:
view_service有两个功能:
1、 清理缓存
2、从缓存中获取视图信息,如果没有则调用orm服务调用model的get_views方法从后端读取, 然后将返回的信息封装成一个对象返回,这个对象包含了

模型的字段信息
模型信息(包括模型的所有字段以及字段的相关信息),relatedModels 在前端是一个非常重要的概念
视图信息(各种类型视图的id,xml结构等)

关于menuService的介绍就告一段落。

这篇关于odoo17核心概念view2——view_service的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/541695

相关文章

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?

一文带你迅速搞懂路由器/交换机/光猫三者概念区别

《一文带你迅速搞懂路由器/交换机/光猫三者概念区别》讨论网络设备时,常提及路由器、交换机及光猫等词汇,日常生活、工作中,这些设备至关重要,居家上网、企业内部沟通乃至互联网冲浪皆无法脱离其影响力,本文将... 当谈论网络设备时,我们常常会听到路由器、交换机和光猫这几个名词。它们是构建现代网络基础设施的关键组成

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

详解MySQL中DISTINCT去重的核心注意事项

《详解MySQL中DISTINCT去重的核心注意事项》为了实现查询不重复的数据,MySQL提供了DISTINCT关键字,它的主要作用就是对数据表中一个或多个字段重复的数据进行过滤,只返回其中的一条数据... 目录DISTINCT 六大注意事项1. 作用范围:所有 SELECT 字段2. NULL 值的特殊处

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP