Chart.js does not get the updated value from Flask - javascript

Working on a project here where I take values from an API, using Flask. And then adding it to a chart using chart.js
I got it to work somewhat, issue I am having is that the variable I use to add the value to the chart with, but it does not change the variable, I add to the chart, whenever the value changes in the API.
Meaning:
Sell Price: 10.3
sell price change to 10.4
Sell Price: 10.3 <-- It does not change to 10.4
Here is my python code for it:
#app.route('/product/<product>')
def productPage(product):
price = []
data = requests.get(
'https://api.hypixel.net/skyblock/bazaar?key=').json()
sell = data['products'][product]['sell_summary']
for x in sell:
price.append(x['pricePerUnit'])
currentSell = data['products'][product]['sell_summary'][0]['pricePerUnit']
return render_template('product.html', product=product, price=price, currentSell=currentSell)
#app.route('/graph_update/<product>', methods=['GET', 'POST'])
def graph_update(product):
data = requests.get(
'https://api.hypixel.net/skyblock/bazaar?key=').json()
currentSell = data['products'][product]['sell_summary'][0]['pricePerUnit']
return jsonify('', render_template('graph_update.html', currentSell=currentSell))
And here HTML/JS:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="container" style="position: relative; height: 40vh; width: 80vw">
<canvas style="width: 25%" id="myChart"></canvas>
</div>
<input
type="button"
value="add data"
style="margin-top: 25%"
onclick="addData()"
/>
<h1 style="padding-top: 25%">{{product}}</h1>
{% for sell in price %}
<p id="sellprice">{{ sell }}</p>
{% endfor %}
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script>
var sellprice = JSON.parse("{{ currentSell | tojson | safe }}");
var product = "{{ product }}";
let myChart = document.getElementById("myChart").getContext("2d");
let priceChart = new Chart(myChart, {
type: "line", // bar, horizontalBar, pie, line, doughnut, radar, polarArea
data: {
labels: [],
datasets: [
{
label: "Sell Price",
},
],
},
options: {},
});
var getData = function () {
$.ajax({
url: "/graph_update/" + product,
success: function (data) {
// process your data to pull out what you plan to use to update the chart
// e.g. new label and a new data point
// add new label and data point to chart's underlying data structures
var sellprice = JSON.parse("{{ currentSell | tojson | safe }}");
priceChart.data.labels.push(sellprice);
priceChart.data.datasets[0].data.push(sellprice);
// re-render the chart
priceChart.update();
},
});
};
// get new data every 3 seconds
setInterval(getData, 10000);
</script>
Thanks!

The issue is that your python code at the endpoint /graph_update/<product> should return data as JSON and currently it is doing the following:
return jsonify('', render_template('graph_update.html', currentSell=currentSell))
You need to return something like
return jsonify(data) # or subset of data that you need to pass

Related

Pass Django variables to javascripts

I am stuck into a problem, I want to pass django variable to javascripts but I can't.
views.py
def dashboard_view(request):
months_before = 5
now = datetime.utcnow()
from_datetime = now - relativedelta(months=months_before)
modified_from_datetime = from_datetime.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
month = Btdetail.objects.filter(DatePur__gte=modified_from_datetime).count()
return render(request, "dashboard.html", {'month': month})
I want to embed month value to javascripts data
my html script function is
<script>
var xValues = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
new Chart("myChart3", {
type: "line",
data: {
labels: xValues,
datasets: [{
data: [5,10,20,15,20,5,15,40,10,12,24,35],
borderColor: "red",
fill: false
}]
},
options: {
legend: {display: false}
}
});
</script>
actually I want to create a Area bar, all things are good but javascript functions cant get value from django database and if there is another way to do this please tell me
[1]: https://i.stack.imgur.com/9bJzE.jpg
on your anypage.html inside <body> </body> tag
<body>
<p> text for example </p>
<div> some divs </div>
<script type="text/javascript">
var month_count = {{ month }};
</script>
</body>
it will initiate month_count variable on your anypage.html and you could use it with javascripts inside this anypage.html
views.py
import json
def your_page(request):
context = {
"some_list": json.dumps([1,2,3]),
}
return render(request, "your_template.html", context)
javascript
<script>
const some_list = JSON.parse(`{{some_list|safe}}`);
</script>

All data points are not appearing in a line chart made using chart.js

I am using Django 2.0 for back-end development of a BPO website. In that one, I am trying to show one accounting information (trail balance) of an organisation in a table and two separate line chart for credit and debit accounts.I am using Chart.js for plotting the line chart. The corresponding functions in view.py file of django are:
#this preprocess function is used to find out the credit and debit accounts
def preprocess(a):
label1 = []
label2 = []
arr1 = []
arr2 = []
for i in range(len(a)):
if int(a[i,1])!=0:
label1.append(a[i,0])
arr1.append(int(a[i,1]))
else:
label2.append(a[i,0])
arr2.append(int(a[i,2]))
return label1,label2,list(arr1),list(arr2)
#login_required
def Acc_Info(request):
obj = request.user
if(request.method=='GET'):
obj1 = Company.objects.get(username=obj)
dt = int(datetime.date.today().year)
obj2 = AccountingInfo.objects.filter(company_code=obj1,date=dt)
if obj2.exists():
obj2 = AccountingInfo.objects.get(company_code=obj1,date=dt)
path = settings.MEDIA_ROOT+'/'+str(obj2.info)
# names = ['Name of Account','Credit','Debit']
data = pd.read_csv(path)
data = np.array(data)
# dr = list(data[:,1])
# cr = list(data[:,2])
label1,label2,dr,cr = preprocess(data)
print("\n\ncr = ",cr)
print("\n\ndr = ",dr)
Debit_sum = data[:,1].sum(dtype=np.float64)
Credit_sum = data[:,2].sum(dtype=np.float64)
return render(request,'Acc_Info.html',{'f':True,'lc':len(cr),'lr':len(dr),'label1':label1,'label2':label2,'cr':cr,'dr':dr,'year':datetime.date.today().year,'data':data,'Suspense':Credit_sum-Debit_sum,'Credit_sum':Credit_sum,'Debit_sum':Debit_sum})
else:
return render(request,'Acc_Info.html',{'f':False,'year':dt})
else:
obj1 = Company.objects.get(username=obj)
dt = request.POST['year']
obj2 = AccountingInfo.objects.filter(company_code=obj1,date=dt)
if obj2.exists():
obj2 = AccountingInfo.objects.get(company_code=obj1,date=dt)
path = settings.MEDIA_ROOT+'/'+str(obj2.info)
data = pd.read_csv(path)
data = np.array(data)
label1,label2,dr,cr = preprocess(data)
print("\n\ncr = ",cr)
print("\n\ndr = ",dr)
Credit_sum = data[:,2].sum(dtype=np.float64)
Debit_sum = data[:,1].sum(dtype=np.float64)
return render(request,'Acc_Info.html',{'f':True,'lc':len(cr),'lr':len(dr),'label1':label1,'label2':label2,'cr':cr,'dr':dr,'year':dt,'data':data,'Suspense':Credit_sum-Debit_sum,'Credit_sum':Credit_sum,'Debit_sum':Debit_sum})
else:
return render(request,'Acc_Info.html',{'f':False,'year':dt})
return redirect('/HRO/log_in/')
My HTML file is as follows:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js" integrity="sha256-oSgtFCCmHWRPQ/JmR4OoZ3Xke1Pw4v50uh6pLcu+fIc=" crossorigin="anonymous"></script>
<title>
Accounting Information
</title>
</head>
<body>
<div class="text-center">
<h2>Select Year for Checking the particular Account Information of that year</h2>
</div><br><br>
<div class="text-center">
<form method="post">
{% csrf_token %}
<label>Year: </label>
<select id="year" name="year"></select>
<button type="submit" class="btn btn-primary">Submit</button>
</form><br>
</div>
<script type="text/javascript">
var start = 2000;
var end = new Date().getFullYear();
var options = "";
for(var year = start ; year <=end; year++){
options += "<option>"+ year +"</option>";
}
document.getElementById("year").innerHTML = options;
</script>
<div class="container">
<h2>Accounting Information for the Year: {{ year }}</h2>
{% if f %}
<table class="table table-hover table-stripe">
<thead><tr>
<th>NAME OF ACCOUNT</th>
<th>DEBIT</th>
<th>CREDIT</th>
</tr>
</thead>
<tbody>
{% for value in data %}
<tr>
{% for any in value %}
<td>{{ any }}</td>
{% endfor %}
</tr>
{% endfor %}
<tr>
<td><strong>Total:</strong></td>
<td>{{ Dredit_sum }}</td>
<td>{{ Crebit_sum }}</td>
</tr>
</tbody>
</table>
<label>Suspense Account: {{ Suspense }}</label>
</div>
<canvas id="myChart1" width="400" height="400" class="col-md-4 offset-md-10"></canvas>
<canvas id="myChart2" width="400" height="400" class="col-md-4 offset-md-10"></canvas>
</body>
{% else %}
<h1>It Seems you have not uploaded Account Information for the chosen year</h1><br>
{% endif %}
<script type="text/javascript">
//if({{ f }})
//{
var ctx = document.getElementById("myChart1").getContext('2d');
var ctx2 = document.getElementById("myChart2").getContext('2d');
// var backgroundColor1 = []
// var backgroundColor2 = []
// var border1 = []
// var border2 = []
// for(var i=0;i<{{ ld }};i++)
// {
// backgroundColor1.push('rgba(255, 99, 132, 0.5)');
// border1.push('rgba(255,99,132,1)');
// }
// for(var i=0;i<{{ lc }};i++)
// {
// backgroundColor2.push('rgba(132, 99, 255, 0.5)');
// border2.push('rgba(132,99,255,1)');
// }
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Debit Accounts',
data: {{ dr }},
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
responsive: false
}
});
var myChart2 = new Chart(ctx2, {
type: 'line',
data: {
datasets: [{
label: 'Credit Accounts',
data: {{ cr }},
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
},
responsive: false
}
});
//}
</script>
</html>
I have 2 questions:
1. Why is this plotting only first two data points
2. How to set a default colour in Chart.js charts, because the 'fillColor' method is not supported in this Chart.js version
The screen is appearing like this:
The accounting info in table( it is appearing properly)
The chart are as follows:
The line charts( Only two points are appearing)
P.S. It will be very helpful if I get some prompt answer because I have a project to submit. Thank you in advance :).

Django template tag, making my list empty or I'm not pass anything

Thanks for reading my post
okay, I'm currently working on Django project that displays data in a dashboard; I manage to display and draw charts with Chart JS, great but now I need to limited number data in Django database to be displayed on charts and display the most recent data put into the database.
I use Django built-in tag to display the most recently is "last" and limiting the display data, the tag is "length_is"(Solve).
Here are my HTML codes for using the "last" tag and index page
<div class = "containor">
<div class = "float-right my-4 chartjs-render-monitor" id="chartContainerPH" style="width: 49%; height: 400px;display: inline-block; background-color:#FDFDFD;">
<center>
<a class="title-link" href="{%url 'ph' %}">PH:</a>
<p>{% for tank_system in tank %} {{tank_system.ph|last}} {%endfor%}</p>
</center>
{%include 'FrounterWeb/includes/PHchart.html'%}
</div>
This is the result I get Last Tag result in my index
(Solve)
Here' my code for chart HTML which I use the length_is tag
{%block PHchart%}
<canvas class = "my-4 chartjs-render-monitor" id="PHchart" ></canvas>
<script>
var ctx = document.getElementById("PHchart");
var PHchart = new Chart(ctx, {
type: 'line',
data: {
labels: [ {%for tank_system in tank%} "{{tank_system.datetime}}", {%endfor%} ], //x-Axis
datasets: [{ //y-Axis
label: 'PH1',
data: [ {%for tank_system in tank%} {{tank_system.PH|length_is:"3"}}, {%endfor%} ],
backgroundColor: "rgb(249, 24, 24,0.2)",
borderColor: "rgb(249, 24, 24,0.2)",
fill: true,
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:false
}
}]
}
}
});
</script>
</div>{%endblock%}
and the result Length_is on chart
Summary: I can't get the built-in "filter" and "length_is"(Solve) Django tags to work. Could you please share an example or tutorial with me? The Django documentation didn't write many examples.
and here my views codes;
#login_required(login_url='/accounts/login/')
def index(request):
tank = tank_system.objects.all()
args = {'tank':tank}
return render(request,'FrounterWeb/extends/includes.html',args)
and my models' codes;
class tank_system(models.Model):
PH = models.DecimalField(max_digits=3, decimal_places=1)
EC = models.DecimalField(max_digits=3, decimal_places=1)
WaterLevel = models.IntegerField(default=100)
TempWater = models.IntegerField(default=0)
TempRoom = models.IntegerField(default=0)
datetime = models.DateTimeField(default=timezone.now())
Both of these filters are well documented in the django docs. The last filter gets you the last element of a list, and the length_is filter returns True if the list is that length, or False otherwise.
This likely means that there is an issue in your understanding of your code. You'll want to verify the type and the values of tank_system.PH or tank_system.ph (you have both) and the case will matter. One way to debug this is to simply output the value of tank_system.ph to the web page and verify the result.

Django - Best way to refresh a div in a Template using Javascript?

I want to refresh the <div> that my google chart is embedded in every 30 seconds to display updates to the data in the model that it is using.
here is the template:
metrics.html
{% extends 'metrics/metrics_header.html' %}
{% block content %}
<h1>Metrics</h1>
<p>Submitted = {{ submitted }},
Conforming = {{ conforming }}
Transcoding = {{ transcoding }}
Complete = {{ complete }}
Error = {{ error }}
</p>
<script type="text/javascript">
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Job State', 'Jobs', { role: "style" }],
['Submitted', {{ submitted }},'blue'],
['Conforming', {{ conforming }},'purple'],
['Transcoding', {{ transcoding }},'yellow'],
['Complete', {{ complete }},'green'],
['Error', {{ error }},'red']
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{ calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation" },
2]);
var options = {
title: "Total Number of Jobs Processed",
bar: {groupWidth: "100%"},
legend: { position: "none" },
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);
}
</script>
<div id="columnchart_values" style="width: 100%; height:600px;"></div>
{% endblock %}
I have been using this to refresh the entire page: :
<script>
setTimeout(function(){
window.location.reload(true);
}, 5000);
</script>
As you can imagine it looks really bad when the entire page reloads every 5 seconds, is there a more ecstatically pleasing way to reload the <div>'s that contain jinja2 variables?
I solved my problem using Jquery .load().
setInterval(function () {
$("#div-you-want-to-reload").load("url-for-source-content");
}, 1000); // This reloads the <div> every 1 second.
I am using this with Django so I had to create a view to create the "url-for-source-content" and then reverence that in my url patterns for that app.

Meteor and ChartJS dynamically create a chart

I'm currently working on a project with Meteor. It is used to create, edit, delete and vote for polls. Now I'd like to have a page where you can see the results of the answers shown with "ChartJS".
I got following code:
Templates:
<template name="pollAnalysis">
<h3>Auswertung {{title}}</h3>
{{#each questions}}
{{> questionAnalysis}}
{{/each}}
</template>
<template name="questionAnalysis">
<div class="post">
<div class="post-content">
<h3>{{question}}</h3>
{{> analysisChart}}
</div>
</div>
</template>
<template name="analysisChart">
<canvas id="{{_id}}" class="mychart" height="400" width="400"></canvas>
</template>
Helpers:
Template.pollAnalysis.helpers({
questions: function(){
return Questions.find({pollId: this._id});
}
});
First I had the problem that the chartjs didn't get display, I fixed it by doing this (just for a single ID, thats where I get stuck)
Template.analysisChart.rendered = function(){
drawChart();
}
function drawChart(){
var data = [
{
value: 10,
color:"#27AE60",
highlight: "#2ECC71",
label: "trifft zu"
},
{
value: 10,
color: "#16A085",
highlight: "#1ABC9C",
label: "trifft eher zu"
}
]
var ctx = $("#Cb8CdtDpdKA9y4Hij").get(0).getContext("2d");
var myNewChart = new Chart(ctx);
new Chart(ctx).Pie(data);
}
Now I need the drawChart dynamically.
pseudo code:
function drawChart(questionId){
var data = [
{
value: Questions_Users.find({questionId: questionId}, answer: "yes").count(),
color:"#27AE60",
highlight: "#2ECC71",
label: "trifft zu"
},
{
value: Questions_Users.find({questionId: questionId}, answer: "no").count(),
color: "#16A085",
highlight: "#1ABC9C",
label: "trifft eher zu"
}
]
var ctx = $("#"+questionId).get(0).getContext("2d");
var myNewChart = new Chart(ctx);
new Chart(ctx).Pie(data);
}
So I have to give over the questionId from the Template.analysisChart.rendered to the drawChart() function. But how can I get the questionId ("{{_id}}" in analysisChart template) of the current element in the Template.analysisChart.rendered function?
Greetings & happy programming
faebuk
A quick answer would be to use something like
Template.analysisChart.rendered = function(){
Tracker.autorun(function(){
var data = Questions_Users.find();
drawChart();
})
}
Or look into observeChanges, something like:
Template.analysisChart.rendered = function(){
Questions_Users.find().observeChanges({
added:function(id, fields){
//update Chart.datasets
Chart.update()
}
})
}
I have an example project that just implements the update logic with Tracker and an ReactiveArray (tracker is part of Meteor's front-end, ReactiveArray is similar to Minimongo with fetch): https://github.com/Slava/jsconf-asia-demo/blob/master/tracker.html#L47-L61
To adapt it to a Meteor app, you would start an autorun in template's rendered callback and depend on the minimongo query that you fetch and feed to Chart.js. Once you done, tell Chart.js to update itself.

Categories