I need to do a graph with ChartJs from my Expenses.
This is my view
#login_required
def index(request):
truncate_month = connection.ops.date_trunc_sql('month', 'date_reg')
expense = Expense.objects.extra({'month': truncate_month}).values('month').annotate(Sum('total_amount'))
return render(request, 'home/index.html', {"expense": expense})
On my template
{{ expense }}
And It shows the data in the following format:
[{
'month': '2015-12-01',
'total_amount__sum': 900.0
}, {
'month': '2016-01-01',
'total_amount__sum': 19334.0
}]
How can I format that data to be compatible with chartjs?
ChartJs Example:
labels: ["January", "February", "March", "April", "May", "June", "July"], //Here the month
datasets: [{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40] //here 'total_amount__sum'
},
...
As bryanph said use Values_list, and then to change the quotes from ASCII you need to escape them in the template. You can use the safe filter.
Line in View:
expenses = expense.values_list('month', flat=True)
Template:
{{ expense|safe }}
Take a look at values_list: https://docs.djangoproject.com/es/1.9/ref/models/querysets/#values-list
This gives you lists of values rather than dictionaries.
One way is to hook up underscore.js:
return render(request, 'home/index.html', json.dumps({"expense": expense}))
in the template:
data = JSON.parse({{ expense|safe }});
var labels = _.pluck(data, 'month');
var data = _.pluck(data, 'total_amount__sum');
Related
I'm new to Javascript and now I'm tasked to display charts with Chart.js. I did grouping in Python and used Flask to build the web app. However, my chart is somehow not displayed and I'm not sure why.
HTML
<canvas id="barchart2" width="600" height="400"></canvas>
JS
<script>
var config = {
type: 'bar',
labels : [
"52",
"51",
"54",
"53",
"46",
"82",
"57",
"48",
"50",
"56",
],
datasets : [
{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data : [
611,
18,
11,
10,
9,
8,
6,
3,
2,
2,
]
}
]
},
options: {
legend: {
display: true,
},
title: {
display: true,
text: 'Top 10 District in Singapore',
}
},
};
window.onload = function() {
var ctx = document.getElementById("barchart2").getContext("2d");
window.myBar = new Chart(ctx, config);
};
</script>
When I used this JS instead
var barData = {
labels : [{% for item in lbl1 %}
"{{item}}",
{% endfor %}],
datasets : [
{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data : [{% for item in val1 %}
{{item}},
{% endfor %}]
}
]
}
// get bar chart canvas
var mychart = document.getElementById("barchart2").getContext("2d");
// draw bar chart
new Chart(mychart).Bar(barData);
It worked perfectly (note: without options. I tried to add options, but the options doesn't show although the charts still appears. That's why I wanna change to this format instead).
But when I use the window.onload function, the chart doesn't appear at all.
Would appreciate your help. Thanks!
Could you paste here the complete generated JS code with the data? Or review your data, because I think that might be the problem somehow.
Here's a JSFiddle with your original code (sans your data) that works:
https://jsfiddle.net/wj80597q/5/
var config = {
type: 'bar',
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
data: [0, 10, 5, 2, 20, 30, 45]
}]
},
options: {
legend: {
display: true,
},
title: {
display: true,
text: 'Top 10 District in Singapore',
}
},
};
(function() {
var ctx = document.getElementById("barchart2").getContext("2d");
window.myBar = new Chart(ctx, config);
})()
Right now I am implementing line chart in angular js. And I have written one directive for this, So it is working fine, But when I am putted $watch in this directive then every time chart will updating continuously. I want to use $watch for some dynamic change after loaded the page.
angular.module('app.abc').directive('linechart', function () {
return {
restrict: 'A',
template:'',
link: function (scope, element, attributes) {
scope.$watch(function(){
var lineOptions = {
scaleShowGridLines : true,
scaleGridLineColor : "rgba(0,0,0,.05)",
scaleGridLineWidth : 1,
bezierCurve : true,
};
var lineData = { labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var ctx = element[0].getContext("2d");
var myNewChart = new Chart(ctx).Line(lineData, lineOptions);
})
}
}
});
<canvas style="display: block;" linechart height="120" ></canvas>
Line chart reflecting updates is contiguously. But I don't want to reflection continuously. I have tried to put my ctx object outside of $watch, but chart is not showing anything. Actually I am new in angular js and also new in directives. Please give me idea how handle this directive with $watch. I have seen one demo(based on javascript) example https://codepen.io/SitePoint/pen/mJRrKw
The chart js v2 is overlapping with is there a way to move the labelString of scaleLabel further down so that it does not overlap.Please view the screen shot marked in yellow and red part.
Part of the code is as following
scales: {
xAxes: [{
display: true,
ticks: {
autoSkip: false,
autoSkipPadding: 20
},
scaleLabel: {
display: true,
labelString: "ProductName(ProductName)"
}
}],
There are two possible solutions to your problem:
1: This is for a line chart, but can easily tailored to a bar chart.
The legend is part of the default options of the ChartJs library. So
you do not need to explicitly add it as an option.
The library generates the HTML. It is merely a matter of adding that
to the your page. For example, add it to the innerHTML of a given DIV.
(Edit the default options if you are editing the colors, etc)
<div>
<canvas id="chartDiv" height="400" width="600"></canvas>
<div id="legendDiv"></div>
</div>
<script>
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "The Flash's Speed",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65, 59, 80, 81, 56, 55, 40]
},
{
label: "Superman's Speed",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28, 48, 40, 19, 86, 27, 90]
}
]
};
var myLineChart = new Chart(document.getElementById("chartDiv").getContext("2d")).Line(data);
document.getElementById("legendDiv").innerHTML = myLineChart.generateLegend();
</script>
2: Adding a legend template in chart options
You'll also need to add some basic css to get it looking ok.
//legendTemplate takes a template as a string, you can populate the template with values from your dataset
var options = {
legendTemplate : '<ul>'
+'<% for (var i=0; i<datasets.length; i++) { %>'
+'<li>'
+'<span style=\"background-color:<%=datasets[i].lineColor%>\"></span>'
+'<% if (datasets[i].label) { %><%= datasets[i].label %><% } %>'
+'</li>'
+'<% } %>'
+'</ul>'
}
//don't forget to pass options in when creating new Chart
var lineChart = new Chart(element).Line(data, options);
//then you just need to generate the legend
var legend = lineChart.generateLegend();
//and append it to your page somewhere
$('#chart').append(legend);
Either of these two options will work.
In your case the legend code will look something like this
(Assuming you already have a BarChart Generated)
<div id="legendDiv"></div>
document.getElementById("legendDiv").innerHTML = BarChart.generateLegend();
Then use css to format the legend however you would prefer (including adding spacing between the legend in the chart)
in my asp.net webform application i want to send a variable from my codebehind to the .aspx page for using in my js codes
codebehind:
public string GetSomestring()
{
JavaScriptSerializer j = new JavaScriptSerializer();
return j.Serialize("#000");
}
and in my page in js i have this code
<script>
var randomScalingFactor = function () { return Math.round(Math.random() * 100) };
var color= '<%= GetSomestring()%>';
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: color,
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [12,23,12,43,10,3]
}
]
}
window.onload = function () {
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).Line(lineChartData, {
responsive: true
});
}
</script>
the string returned to my .aspx page because when i write the below code it execute rightly
var color = '<%= GetSomestring()%>';
alert(color);
and when i write this code my js execute rightly
var color = "#000";
i dont know what is the problem that my first code not execute rightly and pointStrokeColor not get the "color"
To get value from server in javascript you should use Ajax for that using webmethod in codebehind.
Here is some sample code may it help you.
Code Behind:
[WebMethod]
public string GetSomestring()
{
JavaScriptSerializer j = new JavaScriptSerializer();
return j.Serialize("#000");
}
View: "Client Side"
var result;
$.ajax({
url: ../PageName/GetSomestring",
type: "get",
dataType: "json",
contentType: "application/json;charset=utf-8",
success: function (data, status) {
result = data.d;
},
error: function (requeset, status, error) {
alert(error);
}
});
var color= result ;
OR just try this:
Convert color into color.value
<script>
var randomScalingFactor = function () { return Math.round(Math.random() * 100) };
var color= '<%= GetSomestring()%>';
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: color.value,
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [12,23,12,43,10,3]
}
]
}
window.onload = function () {
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).Line(lineChartData, {
responsive: true
});
}
Convert color into color.value
pointStrokeColor: color.value,
Hopefully this will help you.Thanks
I am working on a code with an API. I need to create a line chart for these things called tickets. I need to call the information for them from the API. It has the ticket ID, date, and description. For the labeling, I have four weeks of the month. If I don't call it for every week, the chart won't show up. However, when I do this, instead of the information on a chart popping up, an alert does with all of the information for each week.
var lineChartData = {
labels: ["Week 1","Week 2","Week 3","Week 4"],
datasets: [{
label: "Tickets",
fillColor: "rgba(100,200,244,0.2)",
strokeColor: "rgba(100,200,244,1)",
pointColor: "rgba(200,255,255,.7)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [$.get("http://velocity.data.wpengine.com:3000/tickets/", function(data){ alert(JSON.stringify(data));}).fail(function() {alert("FAIL");}), $.get("http://velocity.data.wpengine.com:3000/tickets/", function(data){ alert(JSON.stringify(data));}).fail(function() {alert("FAIL");}), $.get("http://velocity.data.wpengine.com:3000/tickets/", function(data){ alert(JSON.stringify(data));}).fail(function() {alert("FAIL");}), $.get("http://velocity.data.wpengine.com:3000/tickets/", function(data){ alert(JSON.stringify(data));}).fail(function() {alert("FAIL");}) ] };
If you need the full code (this has CSS, HTML, and the JavaScript), click here.
$.get does not evaluate to a return value like a normal function call.
When the data is received from http://velocity.data.wpengine.com:3000/tickets/, your callback function gets called. In your case that is
function(data){ alert(JSON.stringify(data));}
You have access to the returned data inside this callback function. And you're just alerting it. Which is why you simply get an alert alone. You need to move your chart drawing code into this call back function. Something like
window.onload = function () {
$.get("http://velocity.data.wpengine.com:3000/tickets/list/", function(data){
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
fillColor: "rgba(100,200,244,0.2)",
strokeColor: "rgba(100,200,244,1)",
pointColor: "rgba(200,255,255,.7)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: data,
},
{
label: "My Second dataset",
fillColor: "rgba(100,200,244,0)",
strokeColor: "rgba(100,200,244,0)",
pointColor: "rgba(200,255,255,0)",
pointStrokeColor: "rgba(255,255,255,0)",
pointHighlightFill: "#rgba(255,255,255,0)",
pointHighlightStroke: "rgba(220,220,220,0)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}]
};
var ctx1 = document.getElementById("chart1").getContext("2d");
window.myLine = new Chart(ctx1).Line(lineChartData, {
showScale: false,
pointDot: true,
responsive: true
});
var ctx2 = document.getElementById("chart2").getContext("2d");
window.myLine = new Chart(ctx2).Line(lineChartData, {
responsive: true
});
....