【发布时间】:2014-12-24 10:22:09
【问题描述】:
我计划对 AJAX 和普通请求使用相同的模板 (Jinja 2)。如果是 AJAX 请求,我不会使用 extends,而对于普通请求,extends 将用于扩展基本模板。
我的问题是,如何区分普通请求和 AJAX 请求?有什么方法可以内省request 对象以确定传入请求是基于 AJAX 还是普通请求?
【问题讨论】:
我计划对 AJAX 和普通请求使用相同的模板 (Jinja 2)。如果是 AJAX 请求,我不会使用 extends,而对于普通请求,extends 将用于扩展基本模板。
我的问题是,如何区分普通请求和 AJAX 请求?有什么方法可以内省request 对象以确定传入请求是基于 AJAX 还是普通请求?
【问题讨论】:
您无法可靠地检测请求是否是通过 AJAX 发出的。一些 Javascript 库可能会将 X-Requested-With 标头设置为 XMLHttpRequest,但由于 X-Requested-With 是 not part of the default set of headers that CORS permits,因此它已经失宠了。
在旧版本的 Flask(版本 1.x 之前)中,提供了 request.is_xhr 来检测此标头是否存在并设置为 XMLHttpRequest,这是在引入 Fetch API 之前用于 AJAX 请求的事实上的 API:
True 如果请求是通过 JavaScript XMLHttpRequest 触发的。这仅适用于支持
X-Requested-With标头并将其设置为 XMLHttpRequest 的库。这样做的库是原型、jQuery 和 Mochikit,可能还有更多。
例子:
{% if not request.is_xhr %}
{% extends "base.html" %}
{% endif %}
或
{% extends "base.html" if not request.is_xhr else "ajax.html" %}
在较新的版本中,您必须手动检查标题:
{% if request.headers.get("X-Requested-With") != "XMLHttpRequest" %}
...
{% endif %}
如果您尝试确定提供 JSON 而不是 HTML,更可靠的方法可能是通过 request.accept_mimetypes 对象的 accept_json property 检查 Accept 标头是否包含 application/json:
# in Python code, in your view, for example:
if request.accept_mimetypes.accept_json:
...
【讨论】:
request.is_xhr 已被弃用,有关推理和替代方法,请参阅this answer。