使用call_kw路由调用后端的方法 - xiaohao0576/odoo-doc GitHub Wiki

Odoo开放了一个/web/dataset/call_kwController,允许登陆的用户通过POST方法调用后端的方法,登陆的用户不止是内部用户,Protal用户也算是用户。 注意,只能调用公开的方法,也就是方法名前面带下划线,或者使用了@api.private装饰器的方法是不能调用的

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

https://github.com/odoo/odoo/blob/591c064b856e72a844b822d917572526ff1a57db/addons/web/controllers/dataset.py#L32-L36

call_kw方法

def call_kw(model, name, args, kwargs):
    """ Invoke the given method ``name`` on the recordset ``model``. """
    method = getattr(model, name, None)
    if not method:
        raise AttributeError(f"The method '{name}' does not exist on the model '{model._name}'")
    api = getattr(method, '_api', None)

    if api:
        # @api.model, @api.model_create -> no ids
        recs = model
    else:
        ids, args = args[0], args[1:]
        recs = model.browse(ids)

    # altering kwargs is a cause of errors, for instance when retrying a request
    # after a serialization error: the retry is done without context!
    kwargs = dict(kwargs)
    context = kwargs.pop('context', None) or {}
    recs = recs.with_context(context)

    _logger.debug("call %s.%s(%s)", recs, method.__name__, Params(args, kwargs))
    result = getattr(recs, name)(*args, **kwargs)
    if api == "model_create":
        # special case for method 'create'
        result = result.id if isinstance(args[0], Mapping) else result.ids
    else:
        result = downgrade(method, result, recs, args, kwargs)

    return result

https://github.com/odoo/odoo/blob/591c064b856e72a844b822d917572526ff1a57db/odoo/api.py#L512-L540

在Chrome中调试

开发的时候,可以在Chrome的开发者工具的console,使用fetch函数进行调试,下面是例子

fetch('/web/dataset/call_kw', {
    method: 'POST', // 指定请求方法为 POST
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        model: 'res.partner',
        method: 'search_read',
	args:[],
	kwargs:{},
	params: {model:'res.partner', method: 'search_read', args:[], kwargs:{}}
    })
})
.then(response => response.json()).then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));

使用POST方法调用后端的服务器动作

odoo还有一个controller,允许调用服务器动作,并以json格式返回结果

    @route('/web/action/run', type='json', auth="user")
    def run(self, action_id, context=None):
        if context:
            request.update_context(**context)
        action = request.env['ir.actions.server'].browse([action_id])
        result = action.run()
        return clean_action(result, env=action.env) if result else False

https://github.com/odoo/odoo/blob/591c064b856e72a844b822d917572526ff1a57db/addons/web/controllers/action.py#L53-L59

⚠️ **GitHub.com Fallback** ⚠️