Home > Enterprise >  use json list element inside a jinja statement using js or jquery
use json list element inside a jinja statement using js or jquery

Time:02-12

this is my code:

                $("select").change(function(){
                $.post("/sort", {sort:$(this).val()}, function(table_data)
                {
                    for (let i in table_data)
                    {
                        var tr = $("<tr/>");
                        var filename = table_data[i].filename;
                        var size = table_data[i].size;
                        var uploaded = table_data[i].upload_time;
                        tr.append("<td>" filename "</td>");
                        tr.append("<td>" size "</td>");
                        tr.append("<td>" uploaded "</td>");
                        **tr.append("<td>" "<a href='{{url_for('.download', filename=***filename***)}}'>" 'Download' "</a>" "</td>")**;
                        tr.appendTo(table);
                    }

Interestingly the jinja statement inside the js statement works, the browser directs to that path, but the filename remains None, because the server, which is using python flask, cannot resolve the value sent from here which is a js variable. Table_data is a json that was returned from the server using jsonify in response to an ajax call. My question is if there's any way to use that 'filename' js variable inside that jinja statement, or perhaps convert it to a jinja variable. Thanks.

CodePudding user response:

As I wrote in my comment, it is only possible to pass variables from Jinja to JavaScript when the page is served. This time has already passed during the AJAX request.

I think the best solution is to construct the url with url_for on the server and transfer it via JSON with the record. So your requirements should be met.

I wrote you a small example, which is based on your question.
All folders in the application's static folder are listed and made available to the user for selection. If he selects a directory, file information and the download URL are queried via Ajax. The information is then displayed in a table.

Flask (app.py)
import os
from datetime import datetime
from flask import Flask
from flask import (
    jsonify,
    render_template,
    request,
    send_from_directory,
    url_for
)

app = Flask(__name__)

@app.route('/')
def index():
    # List all folders in the static folder.
    folders = [file \
        for file in os.listdir(app.static_folder) \
        if os.path.isdir(os.path.join(app.static_folder, file))
    ]
    return render_template('index.html', **locals())

@app.route('/stats', methods=['POST'])
def stats():
    # Return stats of all files in the selected folder.
    if 'target' in request.form:
        data = []
        target = request.form['target']
        try:
            for filename in os.listdir(os.path.join(app.static_folder, target)):
                filepath = os.path.join(app.static_folder, target, filename)
                data.append(
                    {
                        'filename': filename,
                        'filesize': os.path.getsize(filepath),
                        'filetime': datetime.fromtimestamp(os.path.getmtime(filepath)).isoformat(),
                        'filedest': url_for('.download', filename=os.path.join(target, filename))
                    }
                )
            return jsonify(data)
        except OSError: pass
    return '', 400

@app.route('/download/<path:filename>')
def download(filename):
    return send_from_directory(app.static_folder, filename)
HTML (templates/index.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index</title>
  </head>
  <body>
    <select name="target">
      <option disabled selected value>-- select an option --</option>
      {% for folder in folders -%}
      <option value="{{folder}}">{{folder}}</option>
      {% endfor -%}
    </select>

    <table id="my-table" style="width: 100%"></table>

    <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj 3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"></script>

    <script type="text/javascript">
      ((uri) => {
        $(document).ready(function() {
          $('select[name="target"]').change(function(evt) {
            $('table#my-table').empty();
            $.post(uri, { target: $(this).val() })
              .done(function(data) {
                data.forEach(info => {
                  const { filename, filesize, filetime, filedest } = info;
                  const row = $('<tr/>');
                  row.html(`
                    <td>${filename}</td>
                    <td>${filesize}</td>
                    <td>${filetime}</td>
                    <td><a href="${filedest}">Download</a></td>
                  `)
                  row.appendTo($('table#my-table'));
                });
              });
          })
        });
      })({{ url_for('.stats') | tojson }});
    </script>
  </body>
</html>
  • Related