Using Jinja templates with AJAX calls

AJAX Flask Jinja Python

In a Flask framework, one typically renders JINJA templates directly from Python router. This is fine but what if one uses AJAX to add interactivity?

In a Flask framework, one typically renders JINJA templates directly from Python router:

@app.route("/users")
def show_users():
    user_list = get_user_list()
    return render_template("user_list.html", user_list)

This is fine but what if one uses AJAX to add interactivity? Data returned via AJAX is returned to the client side (Javascript), whereas Python code (and thus template rendering) runs server-side. Surely, one can render HTML on the client side directly (or utilize one of the JS template frameworks) but now rendering logic is scattered across different layers, which makes it a nightmare to maintain.

One way to simplify this is to make the API called by AJAX return an already rendered (via Jinja) HTML.

Suppose, you have a REST API to fetch the list of users:

@app.route("/api/v1/get_users", methods=["GET"])
def get_users():
    users = { 0: "root", 42: "bwk" }
    return(jsonify(users))

One could define an additional code path through this API to return the result pre-rendered as HTML:

@app.route("/api/v1/get_users", methods=["GET"])
@app.route("/api/v1/get_users/<do_render>", methods=["GET"])
def get_users(do_render=None):
    users = { 0: "root", 42: "bwk" }

    if do_render:
        return jsonify({ "rendered" : render_template("user_list_fragment.html",
           users) })
    else:
        return(jsonify(users))

..and then render it directly in Javascript:

$.getJSON("http://.../api/v1/get_users",
    true,
    function(data) {
        $('#user-list').html(data["rendered"]);
    }
});
Powered by Jekyll and Moonwalk