How to implement chart.js in Django? - python

I'm trying to visualize my data to a graph using chart.js!
However, I have no idea how that's done...
Could you program experts help me with this, please?
Here's the code I had so far
model.py
class MarksInputOne(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
date = models.DateTimeField(auto_now_add=True)
mark = models.CharField(max_length=200)
def __str__(self):
return self.mark
views.py
def courseOne(request):
marks = MarksInputOne.objects.filter(user=request.user)
total_assign = TodoList.objects.filter(user=request.user)
total = total_assign.count()
this = total_assign.filter(category__name="MAT292H1").count()
return render(request, 'courses/firstcourse.html', {'marks': marks, 'total_assign': total_assign, 'total': total,
'this': this})
def lineChart(request):
labels =[]
data = []
queryset = MarksInputOne.objects.values('mark').filter(category__name='MAT292H1').order_by('date')
for entry in queryset:
labels.append(entry['date'])
data.append(entry['mark'])
return JsonResponse(data={
'labels': labels,
'data': data,
})
and finally, chart.html, this is actually an example code from chart.js
<div class="col">
<div class="col-md">
<h5>Graph</h5>
<hr>
<div class="card card-body">
<canvas id="chart" width="800" height="400"></canvas>
<script>
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [{{data}}],
datasets: [{
label: 'Academic Performance',
data: [{{ labels }}],
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgb(255,99,132)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>
</div>
</div>
</div>
Please help me to implement the data on the chart!
I've been searching through internet for so long, couldn't find anything :((
Thank you for your help!!

All that chart.js cares about is a list of labels, and a list of values. So you'll have to somehow provide it with that. Your lineChart view function responds with a list of labels and a list of datapoints so it suits our needs exactly. What you'll need to do is have your web page send a request to your django server to request the data it should display. When a response is received, you can feed in your data to chart.js and build your chart. Here's a stripped-down code of how all of this fits together from the client's side and from the server's side:
Server Side
def lineChart(request):
return JsonResponse(data = {
'labels': ["Red Label", "Yellow Label"],
'data': [5, 6],
})
Client Side
<canvas id="chart"></canvas>
<script>
let ctx = document.getElementById('chart');
$.ajax({
url: '/lineChart/',
success: function(response){
new Chart(ctx, {
type: 'line',
data: {
labels: response.labels,
datasets: [{
data: response.data
}]
}
});
}
});
</script>
One thing I should point out are the different languages we are dealing with here and how they interact. Django renders an HTML page. During this rendering process, it has access to python variables called context variables. After it's done rendering, it sends that final HTML page to the client. On the client's side is chart.js which is a JavaScript library, it needs JavaScript variables to work with. So using Django's context variables wouldn't really work. ...unless... you use django to render its context variables into the html page as hard-coded javascript-vaild values. I'm guilty of doing this in the past but I would not recommend this approach. It smells awful!

Related

javascript bar chart data no showing

This code gets the total_paid and total_due data:
#http.route('/dashboard', website=True, auth='public')
def TotalItems(self, **kw):
total_paid = 0.0
total_due = 0.0
payslips = request.env['student.payslip'].search([])
for payslip in payslips:
total_paid += payslip.paid_amount
total_due += payslip.due_amount
return http.request.render('daffodil_smartedu_dashboard.dashboard', {
'total_paid': total_paid,
'total_due': total_due
})
and I fetch this data in odoo website like this:
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<canvas id="myChart"></canvas>
<script>
var total_paid = parseFloat(total_paid);
var total_due = parseFloat(total_due);
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Total Paid', 'Total Due'],
datasets: [{
label: 'Amount',
data: [total_paid, total_due],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: { beginAtZero: true }
}]
}
}
});
</script>
The bar chart is showing but the total_paid and total_due data is not showing. When I print this in console it is showing NaN. How can I fetch this data in a bar chart?

How can I send an data to chart.js in python django?

I'm making a project about pull a user github API like this one https://octoprofile.now.sh/user?id=nathannewyen
I don't know how to pass an data to another function in django
Here is my views.py:
def user(req, username):
username = str.lower(username)
# Get User Info
with urlopen(f'https://api.github.com/users/{username}') as response:
source = response.read()
data = json.loads(source)
# Get Limit Call API
with urlopen(f'https://api.github.com/rate_limit') as response:
source = response.read()
limit_data = json.loads(source)
# Get User Repo Info
with urlopen(f'https://api.github.com/users/{username}/repos') as response:
source = response.read()
sorted_by_stars = json.loads(source)
sorted_by_forks = json.loads(source)
sorted_by_size = json.loads(source)
# Sorted by stars
def sort_user_repo_by_stars(sorted_by_stars):
return sorted_by_stars['stargazers_count']
sorted_by_stars.sort(key=sort_user_repo_by_stars, reverse=True)
# Sorted by forks
def sort_user_repo_by_forks(sorted_by_forks):
return sorted_by_forks['forks']
sorted_by_forks.sort(key=sort_user_repo_by_forks, reverse=True)
# Sorted by size
def sort_user_repo_by_size(sorted_by_size):
return sorted_by_size['size']
sorted_by_size.sort(key=sort_user_repo_by_size, reverse=True)
created_at = data['created_at']
created_at = datetime.datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
created_at = created_at.strftime("%B %d, %Y")
context = {
'username': username,
'data': data,
'created_at': created_at,
'limit_data': limit_data,
'sorted_by_stars': sorted_by_stars[:8],
'sorted_by_forks': sorted_by_forks[:8],
'sorted_by_size': sorted_by_size[:8],
}
return render(req, 'user.html', context)
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
labels = ["Blue", "Yellow", "Green", "Purple", "Orange"]
default_items = [23, 2, 3, 12, 2]
data = {
"labels": labels,
"default": default_items,
}
return Response(data)
and here is my urls.py:
from django.urls import path
from . import views
from .views import ChartData
urlpatterns = [
path('', views.index),
path('search', views.searchUser),
path('<username>', views.user),
path('api/chart/data/', ChartData.as_view(), name='api-data'),
]
and here is my templates index.html:
<script>
var endpoint = '/api/chart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function (data) {
labels = data.labels
defaultData = data.default
setChart()
},
error: function (error_data) {
console.log("error")
console.log(error_data)
}
})
function setChart() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: labels,
datasets: [{
label: '# of Votes',
data: defaultData,
backgroundColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
</script>
<div class="card shadow">
<div class="card-body">
<h4 class="card-title">Top Languages</h4>
<div class="line"></div>
<p class="card-text">
<canvas id="myChart" width="150" height="150"></canvas>
</p>
</div>
</div>
I want to make an Top languages used chart like the link that I linked below.
How can I do that in python django?
I really appreciate it
To make your backend and your frontend communicate, you can use some sort of REST API between the two. This is a whole topic on its own so here is a solution to achieve what you want in a simple way.
Your django server is serving HTML files to your client. Those HTML files are called "templates" in the django world because they are rendered by your server. Sadly, once served to the client, you cannot execute python on those pages anymore... Hou have to find another way. Here is an idea:
As you can type JavaScript in an HTML file, you can make django render your data as something JavaScript can understand. JSON for example, or even directly JavaScript code. Keep in mind that this is often seen as a bad practice though, as it will make bugs harder to find.
In our case, we only need two things: x and y values.
Here is how to generate those in python, so that it can be turned into JavaScript:
labels = ['a', 'b', 'c', 'd', 'e']
values = [0, 0, 0, 0, 0]
return render('our_template.html', {
'x': json.dumps(labels),
'y': json.dumps(values),
})
This what we can write in our template to store the data as plain JavaScript variables:
let x = {{ x|safe }}; // this is django template markup language right here
let y = {{ y|safe }}; // it will get evaluated before returning the template to the client
The code above will get rendered as:
let x = ['a', 'b', 'c', 'd', 'e'];
let y = [0, 0, 0, 0, 0];
And here is how you will use them to make a simple bar chart:
window.addEventListener("DOMContentLoaded", event => {
let label = "My chart";
let ctx = document.getElementById('my-chart').getContext('2d');
let accessLogChart = new Chart(ctx, {
type: 'bar',
data: {
labels: x,
datasets: [{
label: label,
data: y,
}]
},
});
});

Django - object is not subscriptable django charts.js" or nothing displays at all?

i'm trying to display data on my charts using some model values and charts.js. My values are a country field and a class method that i'm not sure how I'm to call it.
I keep getting the error
"TypeError: 'Organization' object is not subscriptable django
charts.js" or nothing displays at all. Please help.
models.py
from django_countries.fields import CountryField
class Organization(models.Model):
country = CountryField(blank_label='(select country)')
def Total_Score(cls):
Total_Score = cls.grants_score() + cls.internal_score() #This is a sum of other class methods. This part works as is.
return Total_Score
Views.py
def scores_charts(request):
labels = []
data = []
orgz = Organization.objects.values('country').annotate(Total_Scores=Organization.objects.values('Total_Scores()'))
for org in orgz:
labels.append(org['country'])
labels.append(org['Total_Scores'])
return JsonResponse(data={
'labels': labels,
'data': data,
})
Template.html
<div class="card-block-big">
<canvas id="scores_charts" data-url="{% url 'scores_charts' %}"></canvas>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<script>
$(function () {
var $scores_charts = $("#scores_charts");
$.ajax({
url: $scores_charts.data("url"),
success: function (data) {
var ctx = $scores_charts[0].getContext("2d");
new Chart(ctx, {
type: 'bar',
data: {
labels: data.labels,
datasets: [{
label: 'Scores',
backgroundColor: 'blue',
data: data.data
}]
},
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Scores Bar Chart'
}
}
});
}
});
});
</script>
This error
"TypeError: 'Organization' object is not subscriptable django charts.js"
suggests that you are trying to get an element out of an Organization object that isn't a dictionary, list, or a tuple.
I suspect the likely cause of this may be stemming from the following (though you can confirm this with the full error trace which should tell you the line of code that is causing the error):
for org in orgz:
labels.append(org['country'])
labels.append(org['Total_Scores'])
You should try to debug the values of this and verify that they are correct.

Django integration with Charts.js, I'm unable to find the syntax for passing the data to the template

I'm trying to integrate charts.js charts with django. So far im able to display the pie chart. But the problem im facing is in the bar chart or charts such as where i have not just x and y but x, y1, y2, y3 etc. I'm unable to find the syntax for passing the data to the template
Here's my Model
class due(models.Model):
months= models.CharField(max_length=30)
paid = models.PositiveIntegerField()
unpaid = models.PositiveIntegerField()
def __str__(self):
return "{}-{}".format(self.months, self.paid,self.unpaid)
Here's my View
def graph2(request):
labels = []
data = []
queryset = due.objects.order_by('-paid')[:10]
for Due in queryset:
labels.append(Due.name)
data.append(Due.paid,Due.unpaid)
return render(request, 'account/graph1.html', {
'labels': labels,
'data': data,
})
And this is where i want to access the data from my view, how do i replace the both data fields with my paid and unpaid fields from views. I know the data: {{ data|safe }} this is the syntax but it gets only one column. How do i get y1, y2, y3 etc.
<script>
new Chart(document.getElementById("bar-chart-grouped"), {
type: 'bar',
data: {
labels: ["1900", "1950", "1999", "2050"],
datasets: [
{
label: "Africa",
backgroundColor: "#3e95cd",
data: [133,221,783,2478]
}, {
label: "Europe",
backgroundColor: "#8e5ea2",
data: [408,547,675,734]
}
]
},
options: {
title: {
display: true,
text: 'Population growth (millions)'
}
}
});
</script>
Try to debug your code in the view.py file, by adding print() functions, to see if everything in the business logic works correctly. Also, a note: I do not see any variables ({{ }}) referenced in your template. That means you do not access them inside of it. Please let me know if I helped you, and if I understood your question correctly.

HighStock with Django: help me render

I was hoping someone could help me with my code. I've modified the example from fiddle so that it works with Django web framework, but I can't seem to debug it since it doesn't throw any exception, but the chart doesn't render neither. It's very weird. Essentially, I am redirecting the json datasource to read my own local data.
So far, I have the following code in home.html:
<script src="/static/js/jquery-2.1.0.min.js"></script>
<script src="/static/js/stock/highstock.js"></script>
<script src="/static/js/stock/modules/exporting.js"></script>
<div id="stock_panel" class="stock-body" style="width:100%;height:314px"></div>
<script type="text/javascript">
$(function(){
var chartDataUrl = "{% url 'chartFishPrice' %}";
$.getJSON(chartDataUrl,
function(data) {
// Create the chart
$('#stock_panel').highcharts('StockChart', {
rangeSelector : {
selected : 1,
inputEnabled: $('#stock_panel').width() > 480
},
title : {
text : 'fish Price'
},
series : [{
name : 'chart_data',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
</script>
And this is views.py:
def chartFishPrice(request):
ff = FishCaught.objects.filter(fish_id=1)
data = {'dates': [], 'values': []}
for f in ff:
data['dates'].append(int(f.date_caught.strftime("%s")))
data['values'].append(int(f.num_caught))
data2 = {}
data2['chart_data'] = data
print data2
return HttpResponse(json.dumps(data2), content_type='application/json')
and the urlpatterns:
url(r'^chartFishPrice/$', 'fish.views.chartFishPrice', name='chartFishPrice'),
And I've double checked my data format in json as:
{"chart_data": {"dates": [1396310400, 1396396800, 1396483200, 1396569600], "values": [2, 3, 2, 4]}}
and for comparison, this is the sample data from the example:
[
/* May 2006 */
[1147651200000,67.79],
[1147737600000,64.98],
[1147824000000,65.26]]
This is weird stuff. I really appreciate any help you can spare. Thanks.
But that data doesn't seem to be in the same format at all. You have an object consisting of two arrays, one of "dates" and one of "values". The sample data has an array of arrays, with each sub-array consisting of a single date and a single value.
If you want the same format as the sample, your view should look like this:
data = []
for f in ff:
date = int(f.date_caught.strftime("%s"))
value = int(f.num_caught)
date.append([date, value])

Categories

Resources