Web 控制器¶
控制器¶
控制器需要提供可扩展性,类似于 Model ,但由于先决条件(加载了模块的数据库)可能尚不可用(例如,未创建数据库或未选择数据库),因此无法使用相同的机制。
因此,控制器提供了自己的扩展机制,与模型的机制分离:
控制器通过从 Controller 继承 创建。路由通过使用 route() 装饰的方法定义::
class MyController(odoo.http.Controller):
@route('/some_url', auth='public')
def handler(self):
return stuff()
要 覆盖 一个控制器,从其类 继承 并覆盖相关方法,必要时重新暴露它们::
class Extension(MyController):
@route()
def handler(self):
do_before()
return super(Extension, self).handler()
使用
route()进行装饰是必要的,以保持方法(和路由)可见:如果重新定义方法时未进行装饰,它将被“取消发布”。所有方法的装饰器会被合并,如果覆盖方法的装饰器没有参数,则保留之前的所有装饰器;任何提供的参数都会覆盖之前定义的参数,例如::
class Restrict(MyController): @route(auth='user') def handler(self): return super(Restrict, self).handler()
将把
/some_url的认证方式从公开更改为用户(需要登录)。
API¶
路由¶
- @odoo.http.route(route: str | Sequence[str] | None = None, **routing: typing.Unpack[RoutingOpts])[源代码]¶
装饰控制器方法,以便将匹配给定 URL 和选项的传入请求路由到被装饰的方法。
警告
必须重新装饰在控制器扩展中被覆盖的任何方法,但可以省略参数。详情请参见
Controller。- 参数
route (Union[str, Iterable[str]]) – 被装饰方法服务的路径。与该路由匹配的传入 HTTP 请求路径将被路由到此装饰方法。有关路由表达式的格式,请参阅 werkzeug 路由文档 。
type (str) – 请求类型,可以是
'jsonrpc'或'http'。它描述了在哪里找到请求参数以及如何序列化响应。auth (str) – 认证方法,以下之一: *
'user':用户必须经过认证,当前请求将使用该用户的权限执行。 *'bearer':用户使用 “Authorization” 请求头进行认证,使用带有 API 令牌的 Bearer 方案。请求将使用相应用户的权限执行。如果缺少该头部,请求必须属于认证会话,就像 “user” 认证方法一样。 *'public':用户可能经过认证,也可能没有。如果未认证,当前请求将使用共享的公共用户执行。 *'none':该方法始终处于活动状态,即使没有数据库。主要由框架和认证模块使用。请求代码将没有任何访问当前用户的设施。bearer_scope (str) – 用于对用户进行身份验证的 bearer 令牌的作用域。如果在某条路由上将 bearer_scope 设置为 ‘A’,那么只有以作用域 ‘A’(而非作用域 ‘B’)生成的令牌才能在该端点上对用户进行身份验证。对于
auth='bearer'必须设置,对于其他身份验证方法则不得设置。methods (Iterable[str]) – 此路由适用的 HTTP 方法(动词)列表。如果未指定,则允许所有方法。
cors (str) – Access-Control-Allow-Origin CORS 指令的值。
csrf (bool) – 是否应为该路由启用 CSRF 保护。默认对
'http'类型请求启用,默认对'jsonrpc'类型请求禁用。readonly (Union[bool, Callable[[registry, request], bool]]) – 此端点是否应在只读副本上打开游标,而不是(默认情况下)主读写数据库。
handle_params_access_error (Callable[[Exception], Response]) – 如果从 URL 参数中检索记录时发生错误(访问错误或缺失错误),实现自定义行为。
captcha (str) – 验证码的操作名称。设置后,请求将根据验证码实现进行验证。失败时,这些请求将返回 UserError。
save_session (bool) – 是否应在 http 响应上设置 session_id cookie 并将脏会话保存到磁盘。对于
auth='bearer'默认为False。其他情况默认为True。
请求¶
请求对象会在请求开始时自动设置到 odoo.http.request 上。
- class odoo.http.requestlib.Request(httprequest: odoo.http._facade.HTTPRequest)[源代码]¶
围绕传入 HTTP 请求的包装器,包含反序列化的请求参数、会话工具和请求分发逻辑。
- update_env(user: int | BaseModel | None = None, context: dict | None = None, su: bool | None = None) None[源代码]¶
更新当前请求的环境。
- update_context(**overrides) None[源代码]¶
使用
overrides的值覆盖当前请求的环境上下文。要替换整个上下文,请改用update_env()。
- csrf_token(time_limit: int | None = None) str[源代码]¶
生成并返回当前会话的 CSRF 令牌。
- 参数
time_limit – CSRF 令牌仅在指定的持续时间(以秒为单位)内有效,默认为 48 小时,
None表示令牌在当前用户的会话有效期内一直有效。- 返回
ASCII 令牌字符串
- get_http_params() dict[源代码]¶
从查询字符串和请求体中的表单(包括 application/x-www-form-urlencoded 和 multipart/form-data)提取键值对。
- 返回
合并后的键值对。
- make_response(data: str, headers: HeaderType | None = None, cookies: Mapping | None = None, status: int = 200) Response[源代码]¶
用于非 HTML 响应或带有自定义响应头或 Cookie 的 HTML 响应的辅助工具。
虽然处理器可以直接返回页面的 HTML 标记作为字符串,但如果返回的是非 HTML 数据,则需要创建一个完整的响应对象,否则客户端将无法正确解析返回的数据。
- 参数
data – 响应主体
status – HTTP 状态码
headers – 要设置在响应中的 HTTP 头
cookies – 要在客户端设置的 Cookie
- 返回
一个响应对象。
- make_json_response(data: typing.Any, headers: HeaderType | None = None, cookies: Mapping | None = None, status: int = 200) Response[源代码]¶
用于 JSON 响应的辅助工具,它会对
data进行 JSON 序列化,并在未提供时相应地设置 Content-Type 头。- 参数
data – 将被 JSON 序列化为响应主体的数据
status – HTTP 状态码
headers – 要设置在响应中的 HTTP 头
cookies – 要在客户端设置的 Cookie
- class odoo.http.dispatcher.JsonRPCDispatcher(request)[源代码]¶
-
- dispatch(endpoint, args)[源代码]¶
基于 HTTP 的 JSON-RPC 2 。
我们的实现与规范在两点上有所不同:
JSON-RPC 请求负载中的
method成员被忽略,因为 HTTP 路径已经用于将请求路由到控制器。我们仅支持按名称传递参数结构,即 JSON-RPC 请求负载中的
params成员必须是 JSON 对象,而不是 JSON 数组。
此外,可以通过特殊的
context参数传递一个上下文,以替换会话上下文,该参数会在调用端点之前被移除。成功请求示例:
--> {"jsonrpc": "2.0", "method": "call", "params": {"arg1": "val1" }, "id": null} <-- {"jsonrpc": "2.0", "result": { "res1": "val1" }, "id": null}
产生错误的请求示例:
--> {"jsonrpc": "2.0", "method": "call", "params": {"arg1": "val1" }, "id": null} <-- {"jsonrpc": "2.0", "error": {"code": 1, "message": "End user error message.", "data": {"code": "codestring", "debug": "traceback" } }, "id": null}
响应¶
- class odoo.http.Response(*args, **kwargs)[源代码]¶
带有正文、状态、头部和 QWeb 支持的传出 HTTP 响应。除了
werkzeug.wrappers.Response的参数之外,此类的构造函数还可以接受以下用于 QWeb 延迟渲染的附加参数。- 参数
template – 要渲染的模板
qcontext – 要使用的渲染上下文
uid – 用于 ir.ui.view 渲染调用的用户 id,
None表示使用请求的用户(默认值)
这些属性可作为 Response 对象的参数使用,并且可以在渲染之前的任何时候修改
同时公开
werkzeug.wrappers.Response的所有属性和方法。- classmethod load(fname: str = '<function>') odoo.http.response.Response[源代码]¶
将端点的返回值转换为 Response。
- set_cookie(key, value='', max_age=None, expires=- 1, path='/', domain=None, secure=False, httponly=False, samesite=None, cookie_type='required')[源代码]¶
Werkzeug 中 expires 的默认值为 None,表示会话 cookie。我们希望继续支持会话 cookie,但不将其作为默认行为。现在的默认值是任意设定的 1 年。因此,如果您想要一个会话 cookie,必须显式传递 expires=None。
- add_etag(overwrite: bool = False, weak: bool = False) None[源代码]¶
如果当前响应还没有 etag,则为其添加一个。
在 2.0 版更改: 使用 SHA-1 生成该值。在某些环境中可能无法使用 MD5。
- call_on_close(func: Callable[[], Any]) Callable[[], Any][源代码]¶
将一个函数添加到内部函数列表中,这些函数会在关闭响应时被调用。自 0.7 起,该函数还会返回传入的函数,因此可以将其用作装饰器。
0.6 新版功能.
- delete_cookie(key: str, path: str | None = '/', domain: str | None = None, secure: bool = False, httponly: bool = False, samesite: str | None = None, partitioned: bool = False) None[源代码]¶
删除 cookie。如果键不存在,则静默失败。
- 参数
key – 要删除的 cookie 的键(名称)。
path – 如果要删除的 cookie 仅限于某个路径,则必须在此处定义该路径。
domain – 如果要删除的 cookie 仅限于某个域,则必须在此处定义该域。
secure – 如果为
True,则该 cookie 只能通过 HTTPS 使用。httponly – 禁止 JavaScript 访问该 cookie。
samesite – 将 cookie 的作用域限制为仅附加到 “same-site” 的请求。
partitioned – 如果为
True,则该 cookie 将被分区存储。
- classmethod force_type(environ: WSGIEnvironment | None = None) Response[源代码]¶
强制要求 WSGI 响应是当前类型的响应对象。在许多情况下(例如异常),Werkzeug 会在内部使用
Response。如果在异常上调用get_response(),即使您使用的是自定义子类,返回的也会是一个常规的Response对象。此方法可以强制使用给定的响应类型;并且在提供 environ 时,还会将任意 WSGI 可调用对象转换为响应对象:
# convert a Werkzeug response object into an instance of the # MyResponseClass subclass. response = MyResponseClass.force_type(response) # convert any WSGI application into a response object response = MyResponseClass.force_type(response, environ)
如果您想在主调度器中对响应进行后处理,并使用子类提供的功能,这将特别有用。
请记住,如果可能,这将就地修改响应对象!
- 参数
response – 一个响应对象或 WSGI 应用程序。
environ – 一个 WSGI 环境对象。
- 返回
一个响应对象。
- freeze() None[源代码]¶
使响应对象准备好进行 pickle。执行以下操作:
将响应缓冲到列表中,忽略
implicity_sequence_conversion和direct_passthrough。设置
Content-Length头部。如果尚未设置
ETag头部,则生成一个。
在 2.1 版更改: 移除了
no_etag参数。在 2.0 版更改: 始终会添加
ETag头部。在 0.6 版更改:
Content-Length头部会被设置。
- get_data(as_text: bool = False) bytes | str[源代码]¶
响应正文的字符串表示。每次访问此属性时,响应的可迭代对象都会被编码并展平。如果您流式传输大量数据,这可能会导致不期望的行为。
可以通过将
implicit_sequence_conversion设置为False来禁用此行为。如果
as_text设置为True,返回值将为解码后的字符串。0.9 新版功能.
- get_etag() tuple[str, bool] | tuple[None, None][源代码]¶
返回形如
(etag, is_weak)的元组。如果没有 ETag,返回值为(None, None)。
- get_json(force: bool = False, silent: bool = False) Any | None[源代码]¶
将
data解析为 JSON。在测试时很有用。如果 mimetype 未指示 JSON(application/json,请参阅
is_json),则返回None。与
Request.get_json()不同,结果不会被缓存。- 参数
force – 忽略 mimetype,始终尝试解析 JSON。
silent – 忽略解析错误,改为返回
None。
- iter_encoded() Iterator[bytes][源代码]¶
以响应的编码对响应进行迭代。如果将响应对象作为 WSGI 应用程序调用,则此方法的返回值将用作应用程序迭代器,除非
direct_passthrough已启用。
- make_conditional(request_or_environ: WSGIEnvironment | Request, accept_ranges: bool | str = False, complete_length: int | None = None) Response[源代码]¶
使响应相对于请求具有条件性。如果已为响应定义了 etag,此方法效果最佳。可以使用
add_etag方法来完成此操作。如果在没有 etag 的情况下调用,则仅设置日期头部。如果请求或 environ 中的请求方法不是 GET 或 HEAD,则此方法不执行任何操作。
为在处理范围请求时获得最佳性能,建议响应数据对象实现
seekable、seek和tell方法,如io.IOBase所述。由wrap_file()返回的对象会自动实现这些方法。它不会移除响应的正文,因为这是
__call__()函数自动为我们完成的。返回 self,以便您可以写
return resp.make_conditional(req),但会就地修改该对象。- 参数
request_or_environ – 用于使响应有条件化的请求对象或 WSGI 环境。
accept_ranges – 此参数决定
Accept-Ranges标头的值。如果为False(默认),则不设置该标头。如果为True,则将其设置为"bytes"。如果它是字符串,则使用该值。complete_length – 仅在有效的范围请求中使用。它将设置
Content-Range的完整长度值,并计算Content-Length的实际值。此参数是成功完成范围请求的必备条件。
- Raises
如果
Range标头无法解析或无法满足,则抛出RequestedRangeNotSatisfiable。
在 2.0 版更改: 如果长度为 0,则跳过范围处理,而不是抛出 416 Range Not Satisfiable 错误。
- make_sequence() None[源代码]¶
将响应迭代器转换为列表。默认情况下,如有需要会自动进行此转换。如果禁用了
implicit_sequence_conversion,则不会自动调用此方法,某些属性可能会抛出异常。这也会对所有项进行编码。0.6 新版功能.