简体   繁体   中英

Flask: Render Template and Populate HTML Table

Let me explain my end goal and then maybe that will paint a picture of what I'm trying to do. Here is what my application needs to do:

  1. End user goes to http://www.example.com/ms_bulletins and they see a drop down menu with selectable dates.
  2. Once they select a date, the date is sent to my flask backend and the date is used to query the database for bulletins from that date.
  3. The bulletins should then return to http://www.example.com/ms_bulletins and the table should populate.

I actually have this working almost completely, except for the page does not load to show me the data. Here is some snippets of code:

JavaScript

function dateClick(date){
  var dropdown = document.getElementById("date");
  var date = dropdown.options[dropdown.selectedIndex].value;
  console.log( "Date: " + date );
  $.getJSON($SCRIPT_ROOT + '/ms_bulletins', {
            date: date,
  });
}

Flask

@application.route("/ms_bulletins")
def ms_bulletins():
    date = request.args.get('date', None, type=str)
    session = Session()
    data = session.query(MsBulletins).filter(MsBulletins.date==date)
    bulletins = data.all()
    return render_template("ms_bulletins.html", bulletins=bulletins)

HTML

<script>
$(document).ready( function () {
   $('#bulletin_table').DataTable();
} );
</script>

<div id="select_bulletin_date" onchange="dateClick(this)">
<form>
  <fieldset>
  <legend class="header">MS Bulletin Summary:</legend>
  <select id="date">
    <option name="date" value="11/8/2016">November 2016</option>
    <option name="date" value="10/11/2016">October 2016</option>
  </select>
  </fieldset>
</form>
</div>
<hr>
<div id="ms_bulletins">
<table id="bulletin_table" class="display">
<thead>
    <tr>
        <th>Bulletin ID</th>
        <th>Bulletin KB</th>
        <th>Bulletin Name</th>
        <th>Bulletin Date</th>
    </tr>
</thead>
<tbody>
  {% for bulletin in bulletins %}
    <tr>
        <td><a href="https://technet.microsoft.com/en-us/library/security/{{ bulletin.bulletin_id }}" target="_blank">{{ bulletin.bulletin_id }}</a></td>
        <td><a href="https://support.microsoft.com/en-us/kb/{{ bulletin.kb }}" target="_blank">{{ bulletin.kb }}</a></td>
        <td>{{ bulletin.title }}</td>
        <td>{{ bulletin.date }}</td>
    </tr>
  {% endfor %}
</tbody>
</table>
</div>

Currently when the user goes to http://www.example.com/ms_bulletins , the table is blank, then the user selects a date, I can see the date being passed in the console, and then nothing happens.

If I view the source after the "render template" should have taken place, I can see in the source code that it actually worked:

Source Code

<table id="bulletin_table" class="display">
  <thead>
    <tr>
      <th>Bulletin ID</th>
      <th>Bulletin KB</th>
      <th>Bulletin Name</th>
      <th>Bulletin Date</th>
   </tr>
  </thead>
<tbody>
   <tr>
    <td><a href="https://technet.microsoft.com/en-us/library/security/MS16-142" target="_blank">MS16-142</a></td>
    <td><a href="https://support.microsoft.com/en-us/kb/3198467" target="_blank">3198467</a></td>
    <td>Cumulative Security Update for Internet Explorer</td>
    <td>11/8/2016</td>
  </tr>
  <tr>
    <td><a href="https://technet.microsoft.com/en-us/library/security/MS16-141" target="_blank">MS16-141</a></td>
    <td><a href="https://support.microsoft.com/en-us/kb/3202790" target="_blank">3202790</a></td>
    <td>Security Update for Adobe Flash Player</td>
    <td>11/8/2016</td>
 </tr>
</tbody>
</table>

However, the page itself never loads this data in.

Is what I'm even doing possible? And if so, what is the step I'm missing here?

Based on the information above I think you need to either:

  1. submit the actual form data to the Flask backend, or
  2. modify your async call to modify the actual DOM table

Currently your $.getJSON call is calling your Flask function but you haven't included a method to update the actual HTML page. It's just returning a set of HTML to the browser but not telling the browser to do anything with it. The server side script will run on a GET or POST request, but making this request via XHR does nothing to tell your browser to refresh. The JQuery $.getJSON() call is a way to asynchronously get data from the Flask backend, but to use this functionality you also need to handle the resulting DOM manipulation in Javascript (eg to do this without the page reloading).

DataTables is a great tool. I'm going to ignore it in the first 2 scenarios here and explain how you'd implement this in my third.

So, I think you have 3 options:

1) Have you form POST the data to your Flask application, in this case you'd need to change your view function to accept both GET and POST responses:

@application.route("/ms_bulletins", methods=['GET', 'POST'])

And change your form action to

<form method="POST" action="">

Then remove the Javascript function entirely. This should work, the page will reload on each call.

2) To go the async route would require adding a second Flask function:

from Flask import jsonify

@application.route("/_get_bulletins")
def _get_bulletins():
    date = request.args.get('date', None, type=str)
    session = Session()
    data = session.query(MsBulletins).filter(MsBulletins.date==date)
    bulletins = data.all()
    return jsonify(bulletins)

Then, modify your javascript function to incorporate the results into the DOM:

function dateClick(date){
    var dropdown = document.getElementById("date");
    var date = dropdown.options[dropdown.selectedIndex].value;
    var table = $('#bulletin_table').find('tbody');
    table.empty();
    console.log( "Date: " + date );
    $.getJSON('{{ url_for('._get_bulletins') }}', date, 
        function (data ){
            console.log(data);
            for (var x = 0; x < data.length; x++) {
                var row = $('<tr>');
                row.append($('<td>').text(data[x][0]));
                row.append($('<td>').text(data[x][1]));
                table.append(row);
            }
    });
}

3) Go the Async route and use DataTables. To use this I would recommend passing a more detailed configuration to the DataTables API. It's well documented and powerful. The core functionality to get this to work would be.

Store the DataTable reference in a variable.

var dt = $('#bulletin_table').DataTable();

Change your javascript function to manipulate the DataTable, not the DOM:

function dateClick(date){
    var dropdown = document.getElementById("date");
    var date = dropdown.options[dropdown.selectedIndex].value;
    console.log( "Date: " + date );
    $.getJSON('{{ url_for('._get_bulletins') }}', date, 
        function (data ){
            console.log(data);
            dt.empty();
            dt.rows.add(data).draw();
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM