im new to django and chart js, and trying to develop some project but I was having some trouble when trying to visualize my data from myAPI into chart JS and it shows nothing, here is my code :
var endpoint = '/chart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
urls: 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 ctxSI = document.getElementById("SumberChart");
var SumberChart = new Chart(ctxSI, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: '# of Votes',
data: defaultData,
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: [
'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: {
y: {
beginAtZero: true
}
}
},
});
}
views.py
user = get_user_model()
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
labels = ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange']
defaultitem = [12, 19, 3, 5, 2, 3]
data = {
"labels" : labels,
"default" : defaultitem,
}
return Response(data)
home.html
<div class="col-sm-6 col-xl-6">
<div class=" text-center rounded p-4">
<div class="d-flex align-items-center justify-content-center mb-4" >
<h6 class="mb-0 text-center" style="color: black;">Sumber</h6>
</div>
<canvas id="SumberChart" style="color:black ;"></canvas>
</div>
</div>
Attachment :
My Html
Attachment :
API
it is my first time posing and i really appreciate any ideas to solve my problem, thanks.
You are returning Response(data). I have no idea what type of Response this is. Better return a JsonResponse.
from django.http import JsonReponse
class ChartData(APIView):
# your code
def get(self, request, format=None):
# your code
return JsonResponse(data)
Then in your js script, specify the dataType as json, or parse the data explicitly.
// Specify the dataType as json
$.ajax({
method: "GET",
urls: endpoint,
dataType: "json",
// rest of your code
});
// Explicitly parse data
$.ajax({
success: function(data){
jsonData = JSON.parse(data);
labels = jsonData.labels;
defaultData = jsonData.default;
setChart();
},
// rest of your code
});
Related
I need to create a simple chart (using chart.js),so the should chart like this:
On the Y-axis - the number of registered users,X-axis - date
Screen below:
My model:
class User(AbstractBaseUser, PermissionsMixin):
uid = models.CharField(max_length=36, unique=True, default=make_uid)
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255, unique=True)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
activation_token = models.CharField(null=True, blank=True, max_length=100)
date_joined = models.DateTimeField(default=now, editable=False)
View:
#staff_member_required()
#login_required()
def index(request):
users = User.objects.all()
context = {
"users": users,
"users_count": users.count
}
return render(request, "backoffice/backoffice_index.html", context)
Template part with chart:
<script>
$(document).ready(function () {
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for user in users %} '{{ user.date_joined }}', {% endfor %}],
datasets: [{
label: '# of users registered per day',
data: [],
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: [
'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>
<canvas id="myChart" width="400" height="100"></canvas>
If I understand everything correctly, then I need to put the number of new users in an array called "data",and , obvsiously, it must be integer values !
How could I do it? Thanks in advance !
Because I have a chart on my django app. I also have django-filter on my rest_framework. where I can filter dates. start_date=$start_date&end_date=$end_date
from a typical get data.
def view_info(request):
objs = test.objects.all()
return render(request, 'test.html', {'objs': test})
I want to fetch the data directly to the REST API URL
localhost:8000/api/test/?start_date=$start&end_date=$end
Is it possible? this is how I fetch data from my chart.
<script>
$(document).ready(function(){
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for i in objs %}'{{i.timestamp}}',{% endfor %}],
datasets: [{
label: 'Rainfall Graph',
data: [{% for i in objs %}'{{i.amount}}',{% endfor %}],
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: [
'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>
Here is, in my opinion, the easiest way to do this:
views.py
# inherits APIView, ModelViewSet, etc.
class View(...):
# override get_queryset method like so:
def get_queryset(self):
queryset = self.queryset
custom_filter = self.request.query_params.get('filter')
if custom_filter:
custom_filter = json.loads(custom_filter)
queryset = queryset.filter(**custom_filter)
return queryset
Then we can filter from javascript like so:
script.js
// create the django-like filter:
var filter = JSON.stringify({
'start_date__gte' : '2020-01-01',
'end_date__lte' : '2020-12-31',
})
var url = '.../api/test?filter=' + filter;
Your url will look like:
.../api/test?filter={"start_date__gte":"2020-01-01","end_date__lte":"2020-12-31"}
I'm trying to setup simple application with Ember using ember-chart:
https://www.npmjs.com/package/ember-cli-chart
I have my charts.hbs file:
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
{{#toggle-section}}
<div class="chart-container">
{{ember-chart type=CHARTTYPE data=CHARTDATA options=CHARTOPTIONS width=CHARTWIDTH height=CHARTHEIGHT}}
</div>
{{/toggle-section}}
</div>
</div>
</div>
and my charts.js controller with sample from documentation of Chart.js:
import Controller from '#ember/controller';
import Ember from "ember";
export default Controller.extend({
CHARTTYPE: 'bar',
CHARTDATA: Ember.Computed('', function () {
return {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
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: [
'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
}]
}
}),
CHARTOPTIONS: Ember.Computed('', function () {
return {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
}),
CHARTWIDTH: 500,
CHARTHEIGHT: 500,
});
In index.js route i have redirection to charts route:
beforeModel() {
this.replaceWith('charts');
}
When I am trying to open my localhost:4200 after ember s it gives me an error in console:
router.js:927 Error while processing route: index Ember.Computed is not a function TypeError: Ember.Computed is not a function
I tried to search for an answer but nothing seems to work.
The function is lowercase: Ember.computed
It would also be better to use this import:
import { computed } from '#ember/object';
to avoid having to bring in all of the Ember framework just to access the computed function.
I have seen many solutions for this error but none of them match my case. I know for sure that the init class is getting more than one parameter, but I don't know how to resolve this.
My page has a form which is a dropdown menu. After seleecting a value from the dropdown a list of regions appear in the form of a list. When I click on a item from that list a graph should appear on the same page. So what i have done is, I have created a initial form (class MonthlySalesGraphs) which when filled will render the next page i.e. the view MonthlSalesGraphs_2 which is the same as MonthlySalesGraph but only difference is it displays graphs. But clearly this in not working as this error pops up.
Traceback:
Traceback (most recent call last):
File "C:\Users\Test\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "C:\Users\Test\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Test\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Test\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Test\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\views\generic\base.py", line 89, in dispatch
return handler(request, *args, **kwargs)
File "D:\hemanth\intern2\intern\sales\views.py", line 329, in get
form = self.form_class(request.GET)
TypeError: __init__() takes 1 positional argument but 2 were given
[17/Jul/2018 12:35:39] "GET /sales/monthly-sales/graphs/L11/ HTTP/1.1" 500
73978
views.py
class MonthlySalesGraphs(generic.TemplateView):
form_class = MonthlySalesGraphs
template_name = 'sales/MonthlySalesGraphs.html'
def get(self, request):
if request.user.is_authenticated:
form = self.form_class(request.GET)
if form.is_valid():
zone_code_ = form.cleaned_data['zones']
regions = Region.objects.filter(zone_code=zone_code_)
return render(request, 'sales/MonthlySalesGraphs.html',
{'form': form, 'regions': regions})
return render(request, 'sales/MonthlySalesGraphs.html', {'form':
form})
else:
return redirect('/sales/')
class MonthlySalesGraphs_2(generic.TemplateView):
form_`enter code here`class = MonthlySalesGraphs
template_name = 'sales/MonthlySalesGraphs_2.html'
def get(self, request, region_id):
if request.user.is_authenticated:
form = self.form_class(request.GET)
if form.is_valid():
zone_code_ = form.cleaned_data['zones']
regions = Region.objects.filter(zone_code=zone_code_)
return render(request, 'sales/MonthlySalesGraphs_2.html',
{'form': form, 'regions': regions})
return render(request, 'sales/MonthlySalesGraphs.html', {'form':
form})
else:
return redirect('/sales/')
template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Monthly Sales</title>
{% include 'sales/base.html' %}
{% include 'sales/include.html' %}
</head>
<body>
<div align="center">
<form >
{% include 'sales/form_template.html' %}
<div align="center">
<input type="submit" value="Apply" style="padding: 5px;" >
</div>
</form>
</div>
<div align="left">
<ol>
{% for r in regions %}
<a href="{% url 'sales:mon_sales_graphs_2' r.region_code %}">
<li>{{ r }}</li></a>
{% endfor %}
</ol>
</div>
<table cellpadding="50px">
<tc>
<td>
<div style="width: 500px; height: 500px">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
</td>
</tc>
<tc>
<td>
<div style="width: 500px; height: 500px">
<canvas id="myChart2" width="400" height="400"></canvas>
</div>
</td>
</tc>
</table>
<script>
{% block jquery %}
var endpoint='api/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").getContext('2d');
var ctx2 = document.getElementById("myChart2").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Sales',
data: defaultData,
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: [
'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
}
}]
}
}
});
var myChart2 = new Chart(ctx2, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Sales',
data: defaultData,
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: [
'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
}
}]
}
}
});
}
{% endblock %}
</script>
</body>
</html>
forms.py
class MonthlySalesGraphs(forms.Form):
zone_list = [[0, "---------"]]
for zone in Zone.objects.all():
var = tuple([zone.zone_code, zone.zone_name])
zone_list.append(var)
zones = forms.CharField(label="Zone name",
widget=forms.Select(choices=zone_list))
class Meta:
Model = Zone
fields = ('zone_name')
EDIT:
urls.py
url(r'^$', login, {'template_name': 'sales/login.html'}, name='login'),
url(r'^home/$', views.HomePage.as_view(), name='home-page'),
url(r'^csv-import/$', views.CSVimport, name='csv-import'),
url(r'^monthly-sales/zone-ro/$', views.MonthlySales_Zone_RO.as_view(),
name='mon_sales_z_ro'),
url(r'^monthly-sales/zone-date/$', views.MonthlySales_Zone_Date.as_view(),
name='mon_sales_z_d'),
url(r'ajax/load-regions/$', views.load_regions, name='zone-ro-dropdown'),
url(r'^monthly-sales/graphs/$', views.MonthlySalesGraphs.as_view(),
name="mon_sales_graphs"),
url(r'^monthly-sales/graphs/(?P<region_id>[A-Z][0-9][0-9]*)/$',
views.MonthlySalesGraphs_2.as_view(), name="mon_sales_graphs_2"),
url(r'^monthly-sales/graphs/(?P<region_id>[A-Z][0-9][0-9]*)/api/data/$',
views.MonthlySalesGraphsAPI.as_view(), name="mon_sales_graphs_api"),
So I spent the weekend testing and searching SO and finally got Django and Chart.js working. Kind of. It renders the graph but the data is not correct. When I loop through the object, the results are not what I would expect. Maybe I'm blind from staring at this all weekend. Would appreciate any pointers.
Here are my views...
class ChartView(LoginRequiredMixin, TemplateView):
template_name = 'Books/chart.html'
def get_context_data(self, **kwargs):
context = super(ChartView, self).get_context_data(**kwargs)
qs1 = Class.objects.filter(id__in=self.request.user.userprofile.class.all()).order_by('id')
qs2 = Books.objects.filter(class__in=self.request.user.userprofile.books.all()).distinct()
context['qs1'] = qs1
context['qs2'] = qs2
return context
class ChartData(LoginRequiredMixin,APIView):
model = Books
authentication_classes = (SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
qs_count = Books.objects.filter(class__in=self.request.user.userprofile.class.all()).count()
labels = []
default_items = []
data = {
"labels": labels,
"default": default_items,
}
return Response(data)
Here's my HTML with the Javascript...
{% extends 'base5.html' %}
{% block body_block %}
<div class="box6">
<h1 class="title">Number of Books By Class</h1>
<canvas id="myChart"></canvas>
<div>
<script>
var endpoint = '{% url "Books:chart_data" %}'
var defaultData = [];
var labels = [];
$.ajax({
method: "GET",
credentials: 'same-origin',
url: endpoint,
success: function(data){
labels = data.labels
defaultData = data.default
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for i in qs1 %}{{ i.id }},{% endfor %}],
datasets: [{
label: "# of Books",
data: [{% for j in qs2 %}
{{ j.id }},
{% endfor %}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'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: [
'rgba(255,99,132,1)',
'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
}]
}
})
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
</script>
{% endblock %}
Here are the models.
class Books(models.Model):
book_name = models.CharField(max_length=80,null=True)
description = models.TextField(max_length=264,unique=False)
class = models.ForeignKey(Class,on_delete=models.DO_NOTHING,related_name='classes')
class Class(models.Model):
class_name = models.CharField(max_length=264,unique=True)
teacher = models.ForeignKey(User,null=True,
on_delete=models.CASCADE,related_name="teacher_name")
I feel like my looping logic in qs2 is where the problem is. It is not properly looping through qs2, as it is returning results, but not the proper ones. I'm only trying to get the books out of the the user that match the class, and it's not working. Also, I can only get the "ID" to display on the graph, not the actual foreign key name. I can't figure out how to get the actual foreign key name to display either. Appreciate any help or pointers as to what I'm doing incorrectly. I'm so close!
After working all day with Yusef BH, came to the following solution regarding rendering the data correctly. Of note is that the labels are still not coming through. I have opened up a separate SO issue for the labels. Here is the code that allowed me to display the items correctly on the graph.
My HTML
{% extends 'base5.html' %}
{% block body_block %}
<div class="box6">
<h1 class="title">Number of Books By Author</h1>
<canvas id="myChart"></canvas>
<div>
<script>
var endpoint = '{% url "Books:chart_data" %}'
var defaultData = [];
var labels = [];
array = {{ procedures3 }}
$.ajax({
method: "GET",
credentials: 'same-origin',
url: endpoint,
success: function(data){
defaultData = data.default
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for i in book %}{{ i.id }},{% endfor %}],
datasets: [{
label: "# of Procedures",
data: [{% for j in book_count %}
{{ j }},
{% endfor %}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'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: [
'rgba(255,99,132,1)',
'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
}]
}
})
},
error: function(error_data){
console.log("error")
console.log(error_data)
},
})
</script>
{% endblock %}
Views.py
ChartView
class ChartData(LoginRequiredMixin,APIView):
model = Author
authentication_classes = (SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
default_items = []
labels = []
data = {
"labels": labels,
"default": default_items,
}
return Response(data)
The ChartView
class ChartView(LoginRequiredMixin, TemplateView): template_name = 'Book/chart.html'
def get_context_data(self, **kwargs):
context = super(ChartView, self).get_context_data(**kwargs)
book = Author.objects.filter(id__in=self.request.user.userprofile.author.all()).order_by('id')
books_count = [ Book.objects.filter(author=cls).count() for cls in book ]
context['book'] = book
context['book_count'] = books_count
return context
Try this:
def get_context_data(self, **kwargs):
context = super(ChartView, self).get_context_data(**kwargs)
qs1 = Class.objects.filter(id__in=self.request.user.userprofile.class.all()).order_by('id')
class_names = [ cls.class_name for cls in qs1]
books_count = [ Books.objects.filter(class=cls).count() for cls in qs1 ]
context['qs1'] = class_names
context['qs2'] = books_count
return context
Here i want both the Class and Books queryset to be ordered by class because the order is crucial. Here in the context i inject the Class names and Books count directly in the context.
Use This srcipt in the template:
<script>
var labels = "{{ qs1 }}";
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: Array.from(labels),
datasets: [{
label: "# of Books",
data: [{% for j in qs2 %}
{{ j }},
{% endfor %}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'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: [
'rgba(255,99,132,1)',
'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
}]
}
})
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
</script>
There is no need for ajax request you already got the data from the context
I hope this will work.