3

I am planning to use same templates (Jinja 2) for AJAX and normal requests. If it is an AJAX request I will not use extends and for normal request extends would be used for extending the base template.

My problem is, how do I differentiate between a normal and an AJAX request? Is there any way I can introspect the request object to determine whether the incoming request is AJAX based or a normal request?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Vivek Jha
  • 1,520
  • 3
  • 16
  • 26

1 Answers1

4

You can't reliably detect if the request was made via AJAX. Some Javascript libraries may set the X-Requested-With header to XMLHttpRequest, but since X-Requested-With is not part of the default set of headers that CORS permits, it is falling out of favour.

In older versions of Flask (before version 1.x), request.is_xhr was provided to detect if this header is present and set to XMLHttpRequest, the defacto API for AJAX requests before the introduction of the Fetch API:

True if the request was triggered via a JavaScript XMLHttpRequest. This only works with libraries that support the X-Requested-With header and set it to XMLHttpRequest. Libraries that do that are prototype, jQuery and Mochikit and probably some more.

Example:

{% if not request.is_xhr %}
    {% extends "base.html" %}
{% endif %}

or

{% extends "base.html" if not request.is_xhr else "ajax.html" %}

In newer versions you'd have to check for the header manually:

{% if request.headers.get("X-Requested-With") != "XMLHttpRequest" %}
    ...
{% endif %}

If you are trying to determine to serve JSON instead of HTML, a more reliable method might be to check if the Accept header includes application/json, via the accept_json property of the request.accept_mimetypes object:

# in Python code, in your view, for example:
if request.accept_mimetypes.accept_json:
    ...
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • `request.is_xhr` has been deprecated, see [this answer](https://stackoverflow.com/questions/43871003/identify-if-flask-request-is-from-javascript-or-not) for the reasoning and alternative approaches. – danialk Aug 13 '21 at 06:27
  • 1
    @danialk: thanks for the ping. Not only was it deprecated, it is now firmly gone from recent Flask versions. – Martijn Pieters Aug 16 '21 at 09:36