Python 3.x 如何在odoo 14中设置json类型的路由中的响应状态代码

Python 3.x 如何在odoo 14中设置json类型的路由中的响应状态代码,python-3.x,odoo,response,httpresponse,json-rpc,Python 3.x,Odoo,Response,Httpresponse,Json Rpc,我在Odoo14中创建了一个Json类型的路由 @http.route('/test', auth='public', methods=['POST'], type="json", csrf=False) def recieve_data(self, **kw): headers = request.httprequest.headers args = request.httprequest.args data = request.j

我在Odoo14中创建了一个Json类型的路由

@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
       headers = request.httprequest.headers
       args = request.httprequest.args
       data = request.jsonrequest
所以,当我使用这个路由接收请求时,一切都很好,但是假设我想返回一个不同的状态代码,比如401,我不能使用json类型的路由。 我也尝试过下面的方法,但是这个方法的问题是它会停止所有的odoo请求

from odoo.http import request, Response
@http.route('/test', auth='public', methods=['POST'], type="json", csrf=False)
def recieve_data(self, **kw):
      headers = request.httprequest.headers
      args = request.httprequest.args 
      data = request.jsonrequest
      Response.status = "401 unauthorized"
      return {'error' : 'You are not allowed to access the resource'}
因此,在上面的示例中,如果我将响应状态代码设置为401,则所有其他请求(即使是到不同路由的请求)都将停止,并且其状态代码将更改为401。
我已在odoo14和odoo13中检查了此问题。

您无法指定响应的代码,因为您可以在http.py中看到状态代码是硬编码的:

def _json_response(self, result=None, error=None):

   # ......
   # ......

    return Response(
        body, status=error and error.pop('http_status', 200) or 200,
        headers=[('Content-Type', mime), ('Content-Length', len(body))]
    )
如果结果不是错误,则状态代码始终为
200
。但是你可以直接改变方法的代码,或者如果在结果中指定状态代码并不重要的话,可以使用monkey patch witch(猴子补丁)

一个简单的monkey补丁将它放在模块的
\uuuu init\uuuuu.py
中,您希望该模块具有这种行为

from odoo.http import JsonRequest

class JsonRequestPatch(JsonRequest):

    def _json_response(self, result=None, error=None):
        response = {
            'jsonrpc': '2.0',
            'id': self.jsonrequest.get('id')
            }
        default_code = 200
        if error is not None:
            response['error'] = error
        if result is not None:
            response['result'] = result
            # you don't want to remove some key of another result by mistake
            if isinstance(response, dict)
                defautl_code = response.pop('very_very_rare_key_here', default_code)

        mime = 'application/json'
        body = json.dumps(response, default=date_utils.json_default)

        return Response(
            body, status=error and error.pop('http_status', defautl_code ) or defautl_code,
            headers=[('Content-Type', mime), ('Content-Length', len(body))]
        )
        
        
JsonRequest._json_response = JsonRequestPatch._json_response
在JSON api的结果中,您可以像这样更改状态代码

 def some_controler(self, **kwargs):
        result = ......
        result['very_very_rare_key_here'] = 401
        return result
猴子补丁的风险在于你完全覆盖了这个方法,如果在新版本的Odoo中做了一些更改,你也必须在你的方法中做。
上面的代码来自于
odoo13.0
当我构建一个restfull模块来处理一个网站时,我做了很多这方面的工作,使用
axios
不允许在
GET
请求中发送body。odoo希望参数在
json
request中的正文中。

谢谢,答案非常好。例如,当我从邮递员那里发出请求时,这是很好的。但是如果我打开模块接口,它会抛出错误。因此,为了处理这个问题,我只添加了一个尝试和捕捉。尝试:如果结果中的'custom_status_code':default_code=result.pop('custom_status_code',default_code'),除了异常为e:_logger.warning(“custom Json Request Handling{}.format(str(e)),我的错误忘记了响应可能是直接字典或口述列表,我认为验证响应类型可以避免日志文件中不需要的警告。检查我的编辑,你会明白的