skip to Main Content

I run with success a flask application interfaced with a MySQL database, all running fine.

I’m now trying to build a Dashboard page that will build charts and updates them as the data evolves.
Those charts will be filled-up with dedicated queries defined in the routes and pushed to the proper HTML template with jQuery/Ajax.

I’m stuck at the point where it seems no data gets out of my @home.route > data() function and i can’t figure out why. The error in the debuger tells me that the data is "undefined" (the value data is of float type, containg "." decimals).

My .js knowledge being ridiculously low, i’d appreciate if somebody could help me progress on my error.

Thank you very much.

This is my main route.

@home.route('/admin/dashboard', methods=['GET','POST'])
def data():
    conn = None
    cursor = None
    try:
        conn = mysql.connect()
        cursor = conn.cursor()
        sql = "SELECT location_id, SUM(workload) FROM collaborators GROUP BY location_id ORDER BY DATE(location_id) DESC";
        cursor.execute(sql)
        rows = cursor.fetchall()
        data = []

        for row in rows:
            data.append({'location_id': str(row[0]), 'workload': float(row[1])})

        return jsonify({'payload': json.dumps({'workload':data,'location_id':labels})})

This is my HTML also sheltering the chart script.

<!-- app/templates/home/admin_dashboard.html -->

{% extends "base.html" %}
{% block title %}Admin Dashboard{% endblock %}
{% block body %}
<div class="intro-header">
    <div class="container" style="height:50px">
        <p>Dynamic chart using .JS, Ajax & jQuery</p>
    </div>
    <canvas id="myChart" width="100" height="70"></canvas>
        <script>
                     $(document).ready(function(){
                         var _data;
                         var _labels;
                                  $.ajax({
                                    url: "/admin/dashboard",
                                    type: "get",
                                    dataType:"json",
                                    data:{vals: ''},
                                    success: function(response) {
                                          console.log("This is the returned data: " + JSON.stringify(response));
                                          full_data = JSON.parse(response.payload);
                                          console.log(full_data);
                                          _data = full_data['workload'];
                                          _labels = full_data['location_id'];
                                    },

                                    error: function(error){
                                           console.log("Here is the error res: " + JSON.stringify(error));
                                    }
                                 });

                     // define the chart data
                                var chartData = {
                                  labels : _labels,
                                  datasets : [{
                                        label: 'workload',
                                        fill: false,
                                        borderColor: 'rgba(255, 25, 255, 1.0)',
                                        data: _data,
                                  },
                                  ]
                                }

                     // get chart canvas
                                var ctx = document.getElementById("myChart").getContext("2d");

                    // create the chart using the chart canvas
                                var myChart = new Chart(ctx, {
                                  type: 'bar',
                                  data: chartData,
                                  options: {
                                          legend: { display: true },
                                            title: {
                                             display: false,
                                            text: 'Predicted world population (millions) in 2050'
                                          }
                                        }
                                     });
                     });
    </script>
</div>
{% endblock %}

And finally, this is my base.HTML.

<!-- app/templates/base.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <title>{{ title }} - Proc. Headcount</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/xcharts.min.css') }}"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js "></script>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <script src="{{ url_for('static', filename='js/charts/d3.js') }}"></script>
    <script src="{{ url_for('static', filename='js/charts/sugar.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/charts/xcharts.min.js') }}"></script>

</head>
<body>
    <nav class="navbar navbar-default navbar-fixed-top topnav" style="background-color: #0c0d29;background-color:#000000;" role="navigation">
        <div class="container topnav">
          <div class="navbar-header">
              <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                  <span class="sr-only">Toggle navigation</span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
                  <span class="icon-bar"></span>
              </button>
          </div>
          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
              <div class="logo" >
                  <a href="{{ url_for('home.homepage') }}">
                      <img src="{{STATIC_URL}}../../../static/img/Thales_Logo2.png">
                  </a>
              </div>
             <ul class="nav navbar-nav navbar-right">
                {% if current_user.is_authenticated %}
                  {% if current_user.is_admin %}
                    <li><a class="outward" href="{{ url_for('home.data') }}">Dashboard</a></li>
                    <li><a class="outward" href="{{ url_for('admin.list_functions') }}">Functions</a></li>
                    <li><a class="outward" href="{{ url_for('admin.list_roles') }}">Roles</a></li>
                    <li><a class="outward" href="{{ url_for('admin.list_locations') }}">Locations</a></li>
                    <li><a class="outward" href="{{ url_for('admin.list_collaborator') }}">Collaborators</a></li>
                  {% else %}
                    <li><a href="{{ url_for('home.dashboard') }}">Dashboard</a></li>
                  {% endif %}
                  <li><a class="outward" href="{{ url_for('auth.logout') }}">Logout</a></li>
                  <li><a><i class="fa fa-user"></i>  Hi, {{ current_user.username }}!</a></li>
                {% else %}
                  <li><a href="{{ url_for('home.homepage') }}">Home</a></li>
                  <li><a href="{{ url_for('auth.register') }}">Register</a></li>
                  <li><a href="{{ url_for('auth.login') }}">Login</a></li>
                {% endif %}
            </ul>
          </div>
        </div>
    </nav>
    <div class="wrapper">
      {% block body %}
      {% endblock %}
      <div class="push"></div>
    </div>
    <footer>
        <div class="container">
            <div class="row">
                <div class="col-lg-12">
                    <ul class="list-inline">
                        <li><a href="{{ url_for('home.homepage') }}">Home</a></li>
                        <li class="footer-menu-divider">⋅</li>
                        <li><a href="{{ url_for('auth.register') }}">Register</a></li>
                        <li class="footer-menu-divider">⋅</li>
                        <li><a href="{{ url_for('auth.login') }}">Login</a></li>
                    </ul>
                    <p class="copyright text-muted small">Thales / Procurement</p>
                </div>
            </div>
        </div>
    </footer>
</body>
</html>

2

Answers


  1. Chosen as BEST ANSWER

    Okay i solved my problem I think.

    Thanks to this : Accessing python list in javascript as an array

    The problem was that i was not materializing the interface between my HTML template (hosting the javascript) and my Flask function executing the SQL.

    I abandoned flask.jsonify / dumps method, to directly implement the value/labels names in the render_template(). I still have some improvements to do though.

    Also i modified my script client-side to use {{ data|tojson|safe }}.

    @home.route('/admin/dashboard', methods=['GET','POST'])
    @login_required
    def admin_dashboard():
        # prevent non-admins from accessing the page
        if not current_user.is_admin:
            abort(403)
    
        conn = None
        cursor = None
        try:
            conn = mysql.connect()
            cursor = conn.cursor()
    
            sql = "SELECT location_id, SUM(workload) as workload FROM collaborators GROUP BY location_id;"
            cursor.execute(sql)
            rows = cursor.fetchall()
    
            test = []
            labels = []
    
            for index in range(len(rows)):
                test.append(rows[index][1])
                labels.append(float(rows[index][0]))
            return render_template('home/admin_dashboard.html', title="Dashboard", test = test, labels = labels)
    
        except Exception as e:
            print(e)
        finally:
            if cursor and conn:
                cursor.close()
                conn.close()
    
     <script>
                         $(document).ready(function(){
                            
                             var data = JSON.parse('{{test | tojson | safe}}');
                             var labels = JSON.parse('{{labels | tojson | safe}}');
    
                         console.log(labels)
                                      $.ajax({
                                        url: "/admin/dashboard",
                                        type: "get",
                                        contentType: "application/json; charset=utf-8",
                                        dataType:"json",
                                        data:{vals:''},
                                        success: function(response) {
                                             console.log(response);
                                             full_data = JSON.parse('{{test | tojson | safe}}');
                                             console.log(full_data);
                                             data = full_data['data'];
                                             labels = full_data['labels'];
    
                                        },
                                     });
    
                         // define the chart data
                                    var chartData = {
                                      labels: labels,
                                      datasets : [{
                                            label: 'workload',
                                            fill: true,
                                            borderColor: 'rgba(25, 25, 25, 1)',
                                            backgroundColor:'steelblue',
                                            data: data
                                            }],
                                    }
    
                         // get chart canvas
                                    var ctx = document.getElementById("myChart").getContext("2d");
    
                                    // create the chart using the chart canvas
                                    var myChart = new Chart(ctx, {
                                      type: 'bar',
                                      data: chartData,
                                      options: {
                                              legend: { display: true },
                                                title: {
                                                 display: true,
                                                text: 'Procurement Headcount'
                                              }
                                            }
                                         });
                         });
        </script>
    

  2. for row in rows:
                data.append({'location_id': str(row[0]), 'workload': float(row[1])})
    

    I would try printing what you are returning (the jsonify) to see if that’s correct, and then if it’s not then I would go back to the above line and see if this is how you should be appending to an array of json objects. Will the jsonify accept that?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search