Django Chart Visualization
1. Add chart.js and jquery (layouts.html)
This is currently located at head, but later Iโve to move those scripts down to the end of the body tag.
<!-- layouts.html -->
<!-- head tag -->
...
<!-- Chart js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" integrity="sha256-Uv9BNBucvCPipKQ2NS9wYpJmi8DTOEfTA/nH2aoJALw=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" integrity="sha256-aa0xaJgmK/X74WM224KMQeNQC2xYKwlAt08oZqjeF0E=" crossorigin="anonymous" />
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
...
2. Make a naive chart.html template
<!-- chart.html -->
{% extends 'layouts.html' %} {% comment %} load layouts using extends {% endcomment %}
{%block title%}Chart Page{%endblock%}
{% block content %}
{% comment %} {% include 'slider.html'%} {% endcomment %}
<div class="jumbotron bg-white text-black">
<h1 class="text-center">Chart page</h1><br>
{% comment %} </div>
<div class="row chartContainer">
<div class="column"><canvas id="chart1" style="width:30vw; height:50vh"></canvas></div>
<div class="column"><canvas id="chart2" style="width:30vw; height:50vh"></canvas></div>
</div> {% endcomment %}
{% endblock %}
3. Upload csv file to Django by bulk_create
3-1. Prepare Dataset
csv file with no header.
df.to_csv("yourfile.csv", index=False, header=None)
3-2. Create a Model
# EdaApp/models.py
from django.db import models
# Create your models here.
class Product(models.Model):
InvoiceId = models.CharField(default="", max_length=30) # null=False(default): must have value
Branch = models.CharField(default="", max_length=2)
City = models.CharField(default="", max_length=30)
CustomerType = models.CharField(default="", max_length=6)
Gender = models.CharField(default="", max_length=6)
ProductLine = models.CharField(default="", max_length=30)
UnitPrice = models.FloatField(default=0)
Quantity = models.IntegerField(default=0)
Tax = models.FloatField(default=0)
Total = models.FloatField(default=0)
Date = models.DateField()
Time = models.TimeField()
Payment = models.CharField(default="", max_length=20)
Cogs = models.FloatField(default=0)
GrossMargin = models.FloatField(default=0)
GrossIncome = models.FloatField(default=0)
Rating = models.FloatField(default=0)
Year = models.IntegerField(default=0)
Month = models.IntegerField(default=0)
Day = models.IntegerField(default=0)
3-3. Add data to Model with bulk_create
python manage.py shell
>>> import csv
>>> from EdaApp.models import Product
>>> data = open('market.csv')
>>> reader = csv.reader(data)
>>> reader
<_csv.reader object at 0x7f12b88c0f90>
>>> bulk_list = []
>>> for row in reader:
... bulk_list.append(Product(
... InvoiceId = row[0],
... Branch = row[1],
... City = row[2],
... CustomerType = row[3],
... Gender = row[4],
... ProductLine = row[5],
... UnitPrice = row[6],
... Quantity = row[7],
... Tax = row[8],
... Total = row[9],
... Date = row[10],
... Time = row[11],
... Payment = row[12],
... Cogs = row[13],
... GrossMargin = row[14],
... GrossIncome = row[15],
... Rating = row[16],
... Year = row[17],
... Month = row[18],
... Day = row[19]))
>>> Product.objects.bulk_create(bulk_list)
4. Add ProductChartView to views.py
template_name is dir of the template to use.
Using Sum in django.db.models, doing groupby Branchsโ sum of UnitPrice
For more about annotate, go to appendix.
from django.db.models import Sum
...
class ProductChartView(TemplateView):
template_name = "EdaApp/chart.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['qs'] = Product.objects.all()
context['branch_sum_agg'] = Product.objects.values('Branch').annotate(branch_sum=Sum('UnitPrice'))
return context
context[โbranch_sum_aggโ] looks like:
<QuerySet [{'Branch': 'A', 'branch_sum': 18550.8}, {'Branch': 'B', 'branch_sum': 18478.88}, {'Branch': 'C', 'branch_sum': 18567.76}]>
5. Add the ProductChartView to urls.py
from EdaApp.views import home, eda, ProductChartView
urlpatterns = [
path('admin/', admin.site.urls),
path('', home, name='home'),
path('eda/', eda, name='eda'),
path('chart/', ProductChartView.as_view(), name='chart'),
]
6. Making chart in chart.html
Example of Two chart
6-1. Add scripts block in layouts.html
Content block is used for h1 tag, so create scripts block to its below.
{% block content%}
{% endblock %}
{% block scripts%}
{% endblock %}
6-2. Insert script in chart.html
Create two charts like this:
- Go to chart.html
- loop branch_sum_agg
- get Branch name by x.Branch (labels)
- get branch sum by x.branch_sum (data)
- set label as UnitPrice
{% block scripts%}
<script>
$(document).ready(function(){
var ctx = document.getElementById('chart1');
var chart1 = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for x in branch_sum_agg %}'{{x.Branch}}',{% endfor %}],
datasets: [{
label: 'UnitPrice',
data: [{% for x in branch_sum_agg %}'{{x.branch_sum}}',{% 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: {
responsive: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
})
</script>
<script>
$(document).ready(function(){
var ctx = document.getElementById('chart2');
var chart2 = new Chart(ctx, {
type: 'bar',
data: {
labels: [{% for x in branch_sum_agg %}'{{x.Branch}}',{% endfor %}],
datasets: [{
label: 'UnitPrice',
data: [{% for x in branch_sum_agg %}'{{x.branch_sum}}',{% 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: {
responsive: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
})
</script>
{% endblock %}
6-3. Insert div for chart with two canvases inside of the content block
{% block content %}
<div class="jumbotron bg-white text-black">
<h1 class="text-center">Chart page</h1><br>
<div class='chartContainer'>
<canvas id="chart1" style="width:30vw; height:50vh; display: inline-block; margin-right:200px;"></canvas>
<canvas id="chart2" style="width:30vw; height:50vh; display: inline-block;"></canvas>
</div>
{% endblock %}
class=โchartContainerโ has two canvases.
To align these charts to the center and horizontally, make style to inline-block.
Appendix
<script>
๋ธ๋ผ์ฐ์ ๋ HTML ๋ฌธ์๋ฅผ ์ฒ๋ฆฌํ๋ค๊ฐ <script> ์๋ฆฌ๋จผํธ๋ฅผ ๋ง๋๋ฉด src ์์ฑ์ ๋ช
์๋ ๊ฒฝ๋ก์ ํ์ผ์ ๋ด๋ ค๋ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
์๋์ ๊ฐ์ด <script> ์๋ฆฌ๋จผํธ๊ฐ <body> ์๋ฆฌ๋จผํธ์ ์ค๊ฐ์ ์ค๊ฒ๋๋ฉด ์ด๋ค ์ผ์ด ์ผ์ด๋ ๊น์?
<body>
<h2>A</h2>
<script src="./script.js"></script>
<h2>B</h2>
</body>
์ HTML ๋ฌธ์๋ ๋ธ๋ผ์ฐ์ ์์ ๋ค์๊ณผ ๊ฐ์ด ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
<h2>A</h2>๊ฐ ํ๋ฉด์ ์ถ๋ ฅ๋จ
script.js ํ์ผ์ ๋ด๋ ค๋ฐ์ ์๋ฐ์ค๋ฆฝํธ ์ฝ๋๊ฐ ์คํ๋จ
<h2>B</h2>๊ฐ ํ๋ฉด์ ์ถ๋ ฅ
์ ํต์ ์ผ๋ก HTML ์ ๋ฌธ์๋ค์ <script> ์๋ฆฌ๋จผํธ๋ฅผ <head> ์๋ฆฌ๋จผํธ ์์ ๋ฃ๋๋ก ๋ฐฐ์ฐ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ต๋๋ค. ํ์ง๋ง ์ค์ ํ๋ก์ ํธ์์ ๊ฐ๋ฐ์ ํ๋ค๋ณด๋ฉด <body> ์๋ฆฌ๋จผํธ์ ์ ์ผ ๋ง์ง๋ง์์ <script> ์๋ฆฌ๋จผํธ๋ฅผ ๋ณด๊ฒ๋๋ ๊ฒฝ์ฐ๊ฐ ํจ์ฌ ๋ง๋ค๋ ๊ฒ์ ์ฌ์ฉ์์๊ฒ ๋ณด๋ค ์ต์ ํ๋ ์นํ์ด์ง ๋ก๋ฉ ๊ฒฝํ์ ์ ๊ณตํ๋ ค๋ฉด <script> ์๋ฆฌ๋จผํธ๋ฅผ <body> ์๋ฆฌ๋จผํธ์ ๋ง์ง๋ง์ ๋ฃ๋ ๊ฒ์ด ์ ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
Django annotate Vs. aggregate
>>> from django.db.models import Sum
>>> data = Product.objects.values('Branch').annotate(branch_sum=Sum('UnitPrice'))
>>> data
<QuerySet [{'Branch': 'A', 'branch_sum': 18550.8}, {'Branch': 'B', 'branch_sum': 18478.88}, {'Branch': 'C', 'branch_sum': 18567.76}]>
References
best for chart.js (2 years ago):
https://www.youtube.com/watch?v=1OL5n06kO_w
best for django rest api with chart.js, (4 years ago):
https://www.youtube.com/watch?v=B4Vmm3yZPgc
for multiple charts:
https://canvasjs.com/docs/charts/how-to/render-multiple-charts-in-a-page/
ref:
https://testdriven.io/blog/django-charts/
https://www.freecodecamp.org/news/how-to-create-an-analytics-dashboard-in-django-app/
https://www.youtube.com/watch?v=jrT6NiM46jk
https://dowtech.tistory.com/3
https://m.blog.naver.com/tablesetter/221499332197
https://www.youtube.com/watch?v=B4Vmm3yZPgc
script: https://www.daleseo.com/js-script-defer-async/ csv to django DB: https://velog.io/@swhybein/Django-bulkcreate%EC%9C%BC%EB%A1%9C-csv%ED%8C%8C%EC%9D%BC-%EC%98%AC%EB%A6%AC%EA%B8%B0
django-annotate: https://velog.io/@may_soouu/%EC%9E%A5%EA%B3%A0-Annotate-Aggregate
django-annotate official docs: https://docs.djangoproject.com/en/3.2/topics/db/aggregation/
Leave a comment