当前位置: 首页 > news >正文

宣城公司做网站seo优化报告

宣城公司做网站,seo优化报告,闵行北京网站建设,怎样做英文网站odoo16前端框架源码阅读——ormService.js 路径:addons\web\static\src\core\orm_service.js 简单翻译一下代码中的注释: ORM服务是js代码和python的ORM层通信的标准方法。 然后讲了One2many and Many2many特使的指令格式,每个指令都是3元…

odoo16前端框架源码阅读——ormService.js

路径:addons\web\static\src\core\orm_service.js

简单翻译一下代码中的注释:

ORM服务是js代码和python的ORM层通信的标准方法。

然后讲了One2many and Many2many特使的指令格式,每个指令都是3元组,其中:

第一个参数是固定的整数从0-6,代表指令本身

第二个参数:要么是0(新增记录的时候)要么是关联的记录id(其他update,delete,link,unlink情况)

第三个参数 要么是value(新增或者更新),要么是新的ids(command set) 要么是0,(删除,unlink,link,clear),

再往后,就是几个验证函数,没啥好说的

重点来了:

export class ORM {constructor(rpc, user) {this.rpc = rpc;this.user = user;this._silent = false;}get silent() {return Object.assign(Object.create(this), { _silent: true });}

这里定义并导出了ORM类, 构造函数中引用了rpc和user服务,并且还有一个私有变量_silent, 这个变量暂时不清楚干嘛的,下面这句有意思

 return Object.assign(Object.create(this), { _silent: true });

返回一个同样的orm对象,只是_silent的值编程了true。

这里提一嘴:

Object.create 是创建一个跟自己同样的对象

Object.assign(target,souce1,source2…) 是将第一个对象后面的所有对象的属性付给第一个对象(目标对象),同名的属性会覆盖。

继续往下看call方法,这个是ormService的核心函数

 call(model, method, args = [], kwargs = {}) {validateModel(model);const url = `/web/dataset/call_kw/${model}/${method}`;const fullContext = Object.assign({}, this.user.context, kwargs.context || {});const fullKwargs = Object.assign({}, kwargs, { context: fullContext });const params = {model,method,args,kwargs: fullKwargs,};return this.rpc(url, params, { silent: this._silent });}

首先验证了模型名是否合法, 是否是字符串,并且字符串长度是否等于0,这有点不太严谨啊,怎么也应该验证个.吧,

function validateModel(value) {if (typeof value !== "string" || value.length === 0) {throw new Error(`Invalid model name: ${value}`);}
}

然后就是拼凑params, 就当前用户的context, kwargs.context, kwargs 拼凑成一个对象fullKwargs,然后再跟model,method,args组成一个参数对象params

最后调用rpc, 注意,发送到的url是

 const url = `/web/dataset/call_kw/${model}/${method}`;

我们开看看这个路由都干了啥

文件路径: addons\web\controllers\dataset.py

    @http.route(['/web/dataset/call_kw', '/web/dataset/call_kw/<path:path>'], type='json', auth="user")def call_kw(self, model, method, args, kwargs, path=None):return self._call_kw(model, method, args, kwargs)

我稍微修改了一下代码,将几个参数都打印了出来

    def call_kw(self, model, method, args, kwargs, path=None):print(model)print(method)print(args)print(kwargs)print(path)return self._call_kw(model, method, args, kwargs)

打印结果:

res.users
systray_get_activities
[]
{'context': {'lang': 'zh_CN', 'tz': 'Asia/Shanghai', 'uid': 2, 'allowed_company_ids': [1]}}
res.users/systray_get_activities

这样就一目了然了,

然后调用了内部方法

 return self._call_kw(model, method, args, kwargs)
    def _call_kw(self, model, method, args, kwargs):check_method_name(method)return call_kw(request.env[model], method, args, kwargs)

第一步检查方法名,凡是以下划线开头或者init的方法都不允许远程调用。

def check_method_name(name):""" Raise an ``AccessError`` if ``name`` is a private method name. """if regex_private.match(name):raise AccessError(_('Private methods (such as %s) cannot be called remotely.', name))

然后第二步又调用了call_kw ,这个call_kw 非彼call_kw, 因为前面没有加self,事实上,这个call_kw是从api中引入的

from odoo.api import call_kw

好吧,继续跟踪,到了api中的call_kw

odoo/api.py

def call_kw(model, name, args, kwargs):""" Invoke the given method ``name`` on the recordset ``model``. """method = getattr(type(model), name)api = getattr(method, '_api', None)if api == 'model':result = _call_kw_model(method, model, args, kwargs)elif api == 'model_create':result = _call_kw_model_create(method, model, args, kwargs)else:result = _call_kw_multi(method, model, args, kwargs)model.env.flush_all()return result

跟踪到这里,有点意思了,先获取了model的方法,并获取了方法的_api属性, 这个属性是怎么来的呢, 看到api就想到了那几个装饰器,怀着碰碰运气的想法查看了一下api.py, 下面是我们熟悉的@api.model 的源码,果然是在装饰器里设置了_api这个属性

def model(method):""" Decorate a record-style method where ``self`` is a recordset, but itscontents is not relevant, only the model is. Such a method::@api.modeldef method(self, args):..."""if method.__name__ == 'create':return model_create_single(method)method._api = 'model'return method

到这里就明了了,根据不同的装饰器,调用不同的方法来处理rpc请求。

我们言归正传,继续回到ormService

call后面的函数,其实都是最终都是调用了call方法, 知识在调用之前,传递了不同的参数,这个要结合后台的python代码再去细看,这里就不展开了。

下面是ormService的最后部分:

1、在调用orm方法的时候可以设置一些选项,比如

const result = await this.orm.withOption({shadow: true}).read('res.partner', [id]);

shadow是个什么鬼?

2、终于出现了ormService的定义

它依赖于rpc和user两个服务,rpc发送http请求,而user提供当前用户的上下文环境

列举了支持的方法,这些方法在ORM类中都有定义。

start函数: 参数是env和{rpc,user} 返回了一个ORM实例。

最后注册了这个ormService服务。

/*** Note:** when we will need a way to configure a rpc (for example, to setup a "shadow"* flag, or some way of not displaying errors), we can use the following api:** this.orm = useService('orm');** ...** const result = await this.orm.withOption({shadow: true}).read('res.partner', [id]);*/
export const ormService = {dependencies: ["rpc", "user"],async: ["call","create","nameGet","read","readGroup","search","searchRead","unlink","webSearchRead","write",],start(env, { rpc, user }) {return new ORM(rpc, user);},
};registry.category("services").add("orm", ormService);

附录:ormService.js 代码

/** @odoo-module **/import { registry } from "./registry";/*** This ORM service is the standard way to interact with the ORM in python from* the javascript codebase.*/// -----------------------------------------------------------------------------
// ORM
// -----------------------------------------------------------------------------/*** One2many and Many2many fields expect a special command to manipulate the* relation they implement.** Internally, each command is a 3-elements tuple where the first element is a* mandatory integer that identifies the command, the second element is either* the related record id to apply the command on (commands update, delete,* unlink and link) either 0 (commands create, clear and set), the third* element is either the ``values`` to write on the record (commands create* and update) either the new ``ids`` list of related records (command set),* either 0 (commands delete, unlink, link, and clear).*/
export const x2ManyCommands = {// (0, virtualID | false, { values })CREATE: 0,create(virtualID, values) {delete values.id;return [x2ManyCommands.CREATE, virtualID || false, values];},// (1, id, { values })UPDATE: 1,update(id, values) {delete values.id;return [x2ManyCommands.UPDATE, id, values];},// (2, id[, _])DELETE: 2,delete(id) {return [x2ManyCommands.DELETE, id, false];},// (3, id[, _]) removes relation, but not linked record itselfFORGET: 3,forget(id) {return [x2ManyCommands.FORGET, id, false];},// (4, id[, _])LINK_TO: 4,linkTo(id) {return [x2ManyCommands.LINK_TO, id, false];},// (5[, _[, _]])DELETE_ALL: 5,deleteAll() {return [x2ManyCommands.DELETE_ALL, false, false];},// (6, _, ids) replaces all linked records with provided idsREPLACE_WITH: 6,replaceWith(ids) {return [x2ManyCommands.REPLACE_WITH, false, ids];},
};function validateModel(value) {if (typeof value !== "string" || value.length === 0) {throw new Error(`Invalid model name: ${value}`);}
}
function validatePrimitiveList(name, type, value) {if (!Array.isArray(value) || value.some((val) => typeof val !== type)) {throw new Error(`Invalid ${name} list: ${value}`);}
}
function validateObject(name, obj) {if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {throw new Error(`${name} should be an object`);}
}
function validateArray(name, array) {if (!Array.isArray(array)) {throw new Error(`${name} should be an array`);}
}export class ORM {constructor(rpc, user) {this.rpc = rpc;this.user = user;this._silent = false;}get silent() {return Object.assign(Object.create(this), { _silent: true });}call(model, method, args = [], kwargs = {}) {validateModel(model);const url = `/web/dataset/call_kw/${model}/${method}`;const fullContext = Object.assign({}, this.user.context, kwargs.context || {});const fullKwargs = Object.assign({}, kwargs, { context: fullContext });const params = {model,method,args,kwargs: fullKwargs,};return this.rpc(url, params, { silent: this._silent });}create(model, records, kwargs = {}) {validateArray("records", records);for (const record of records) {validateObject("record", record);}return this.call(model, "create", records, kwargs);}nameGet(model, ids, kwargs = {}) {validatePrimitiveList("ids", "number", ids);if (!ids.length) {return Promise.resolve([]);}return this.call(model, "name_get", [ids], kwargs);}read(model, ids, fields, kwargs = {}) {validatePrimitiveList("ids", "number", ids);if (fields) {validatePrimitiveList("fields", "string", fields);}if (!ids.length) {return Promise.resolve([]);}return this.call(model, "read", [ids, fields], kwargs);}readGroup(model, domain, fields, groupby, kwargs = {}) {validateArray("domain", domain);validatePrimitiveList("fields", "string", fields);validatePrimitiveList("groupby", "string", groupby);return this.call(model, "read_group", [], { ...kwargs, domain, fields, groupby });}search(model, domain, kwargs = {}) {validateArray("domain", domain);return this.call(model, "search", [domain], kwargs);}searchRead(model, domain, fields, kwargs = {}) {validateArray("domain", domain);if (fields) {validatePrimitiveList("fields", "string", fields);}return this.call(model, "search_read", [], { ...kwargs, domain, fields });}searchCount(model, domain, kwargs = {}) {validateArray("domain", domain);return this.call(model, "search_count", [domain], kwargs);}unlink(model, ids, kwargs = {}) {validatePrimitiveList("ids", "number", ids);if (!ids.length) {return true;}return this.call(model, "unlink", [ids], kwargs);}webReadGroup(model, domain, fields, groupby, kwargs = {}) {validateArray("domain", domain);validatePrimitiveList("fields", "string", fields);validatePrimitiveList("groupby", "string", groupby);return this.call(model, "web_read_group", [], {...kwargs,groupby,domain,fields,});}webSearchRead(model, domain, fields, kwargs = {}) {validateArray("domain", domain);validatePrimitiveList("fields", "string", fields);return this.call(model, "web_search_read", [], { ...kwargs, domain, fields });}write(model, ids, data, kwargs = {}) {validatePrimitiveList("ids", "number", ids);validateObject("data", data);return this.call(model, "write", [ids, data], kwargs);}
}/*** Note:** when we will need a way to configure a rpc (for example, to setup a "shadow"* flag, or some way of not displaying errors), we can use the following api:** this.orm = useService('orm');** ...** const result = await this.orm.withOption({shadow: true}).read('res.partner', [id]);*/
export const ormService = {dependencies: ["rpc", "user"],async: ["call","create","nameGet","read","readGroup","search","searchRead","unlink","webSearchRead","write",],start(env, { rpc, user }) {return new ORM(rpc, user);},
};registry.category("services").add("orm", ormService);
http://www.hkea.cn/news/390904/

相关文章:

  • 丽水网站建设明恩玉杰网站开发框架
  • 如何设计网站中的上传功能搜索引擎技术基础
  • 余江区建设局网站百度搜索引擎优化的方法
  • 做网站用c 还是java万网域名注册教程
  • 青岛做网站那家好专业的网站优化公司排名
  • 网站如何做淘宝推广seo服务 收费
  • 学完js了可以做哪些网站营业推广的形式包括
  • 网站会员系统怎么做模版seo是指什么职位
  • 上海集团网站制作新闻 近期大事件
  • 商城网站验收标准seo关键词排名优化怎样收费
  • 睢宁做网站公司珠海百度关键字优化
  • 临安市住房和建设局网站伊春seo
  • 天津百度做网站多少钱游戏代理平台哪个好
  • b2b模式的网站google网站
  • 做优化网站哪个公司好十大营销策略
  • 软件商店app苏州网站关键词优化推广
  • wordpress添加日历首页优化公司
  • 日本可以自己做网站吗查询网站服务器
  • 做网站维护的人叫啥友情链接交换工具
  • 云南网站定制真正永久免费的建站系统有哪些
  • 温州做网站技术员沧州做网络推广的平台
  • wordpress media上海排名优化seobwyseo
  • 深圳网站建设科技有限公司注册一个网站
  • 网站设计改版seo关键词优化推广价格
  • 做网站什么主题比较好上海网站seo诊断
  • 设计苹果手机的网站病毒什么时候才能消失
  • 国外做化工产品的网站自媒体发布平台
  • 怎么做资源类网站百度搜索热度排名
  • 大片网站建设seo关键词排名优化评价
  • 网络营销推广课程培训苏州seo门户网