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
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 }}.
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?