如何在odoo 14中使用json类型设置路由中的响应状态代码

Aem*_*zai 4 response httpresponse json-rpc python-3.x odoo

我在 odoo 14 中创建了一条 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
Run Code Online (Sandbox Code Playgroud)

因此,当我使用此路由收到请求时,一切都很好,但假设我想返回不同的状态代码(如 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'}
Run Code Online (Sandbox Code Playgroud)

因此,在上面的示例中,如果我将响应状态代码设置为 401 ,则所有其他请求(即使它们发送到不同的路由)也将被停止,并且其状态代码更改为 401 。我在odoo14和odoo13中都检查过这个问题。

Cha*_* DZ 9

您无法指定响应的代码,因为您可以看到状态代码被硬编码在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))]
    )
Run Code Online (Sandbox Code Playgroud)

如果结果不是错误,则状态代码始终为200。但是您可以直接更改方法的代码,或者如果在结果中指定状态代码不是很重要,则可以使用猴子补丁女巫,不要这样做 ^^。

一个简单的猴子补丁将其放入__init__.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
Run Code Online (Sandbox Code Playgroud)

在 JSON api 的结果中,您可以像这样更改状态代码

 def some_controler(self, **kwargs):
        result = ......
        result['very_very_rare_key_here'] = 401
        return result
Run Code Online (Sandbox Code Playgroud)

猴子修补的风险是您完全覆盖该方法,如果新版本中的 Odoo 进行了某些更改,您也必须在您的方法中进行更改。上面的代码来自odoo 13.0我在构建一个restfull模块来与网站一起使用时做了很多这样的事情,该axios网站使用不允许在GET请求中发送正文。odoo 期望参数位于jsonrequest 的主体内部。