Building a Basic Analytical App with Django and ChartJS

by Kingsley Ihemere

.

Updated Fri Jul 07 2023

Building a Basic Analytical App with Django and ChartJS

This Django tutorial will teach the Django framework by building a basic data analysis web application that can Create, Read, Update and Delete, otherwise called “CRUD.” For the visualization, we will take advantage of the lightweight and easy-to-use Javascript library called Chartjs.

This article is not geared towards web app development but data analytics applications. 

In this section of our Django tutorial, we will demonstrate how to use Django to create a simple Data Analysis application. With this, we will explore how to set up Django, explore Django Requests and Responses, and discuss the Controller component, and how it interacts with Models and Views.

Prerequisite

To learn Python and Django in detail, there is no better course to recommend personally than Python Django 2021 – Complete Course. Check it out now for a discount.

To understand the Django overview and how the MVT architecture works, please read Django Tutorial: The Ultimate Guide (2021)

Installation

If you’re just starting out creating Django applications with your computer, you need to install the following:

To start, please make sure that python is downloaded to your system. I am using python 3.7 for this project.

I will be using the gitbash terminal and will be working with Windows operating system.

Open your terminal of choice and head on to the directory where you want to house your project. This is just a simple folder you can create anywhere in your system.

It is good practice to create a virtual environment for your different projects. To create a virtual environment, type the below code in your terminal. For the sake of this article, we will choose myvenv as the virtual environment.

pip install virtualenv
virtualenv myvenv

To activate the create virtual environment in windows using gitbash.

source myvenv/Scripts/activate

It is time to download all necessary packages using pip install. Please, download them one at a time for now.

The other packages are:

pip install django
pip install django-heroku
pip install gunicorn
pip install mysqlclient
pip install Django-heroku # ( this will download psycopg2, whitenoise, dj-database-url, and Django-heroku)
pip install python-decouple
pip install whitenoise

Aside from mysqlclient, every other package is for deploying our app on Heroku. We will be using a MySQL database, which is the reason for downloading mysqlclient.

After downloading those packages, the next step is to create a Django project. 

On your terminal, type:

django-admin startproject richestmen

And change the directory into the created project. This is your project’s root folder, and richestmen is my project name.

Note: In Django, we have “project,” and we have “app.” They are created with a different command.

Project:

A Django project is the entire application. It is created before the app(s). Hence, it houses all the apps. 

An App

An app is the submodule of the project. 

Apps are independent of the others in functions. They behave like components in react and vue for those in the Javascripts world. They are also reusable.

When a Django project is created, it comes with a folder and a file. The folder is the same name as the project name, while the file is a manage.py file. This level is called the project’s root folder. The project folder contains other files named below:

  • _init_.py  — This file tells that this is a python project. It helps initialize the project

  • settings.py — This is where the settings for your entire project and apps live.

  • urls.py  – This is where and how you link all your apps and files to the main project

  • wsgi.py – It is used to help your Django application communicate with the webserver.

To confirm your packages, type pip freeze in your terminal. This will bring out all the installed packages.

Then pip freeze > requirements.txt to save it to your root folder.

Your root folder is the same level where you find the file manage.py. You must be in your root folder to execute the above code and any command that involves the manage.py file.

Django’s naming convention means that the first and second-level folders have the same name. 

You can rename only the first folder by typing in your terminal, and it will not affect your project.

mv projectname newprojectname

Next is to make a migration to the database. Django comes with SQLite by default, but I will be using MySQL.

I use MySQL workbench to create my database before making a migration. You can use any database clients of your choice. After completing your database, go to settings.py and update your database as follows.

Note: you must manually create your database.

Setting up database connection

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'databasename',
        'USER': 'root',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

Next is to go to the templates list in settings.py and tell Django where to find HTML files.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

It is time to make the migration. You can migrate using the code below to migrate in your terminal

First, you type in:

python manage.py makemigrations

This will prepare your model for migration by creating a migration file. Next, it will migrate.

python manage.py migrate

At this point, you will notice all the prebuilt models, and your model(s) will populate the database and create the tables.

Django comes with a built-in admin dashboard, but you need to create a superuser to access it. Type the following in your command line and follow the prompt:

python manage.py createsuperuser

If you are using gitbash, use the following command instead:

winpty python manage.py createsuperuser

Now, it is time to log in to your admin. Django comes with a mini server which you can access by running:

python manage.py runserver

If everything is successful, you should find your project running on http://127.0.0.1:8000/. In addition, to access the admin dashboard, simply append admin http://127.0.0.1:8000/admin, then log in with the details you created.

We are done with the setting for now. The next step is to create a Django app. In this case, I chose the name billionaires. 

Here are the commands to create a new Django App:

python manage.py startapp billionaires.

Now open your billionaires folder, you will see different files that may look familiar such as model.py, views.py, and others.

You write your models in model.py, your views in views.py, and you need to create another file name urls.py. I will explain what it does as you move along.

Model

Now, let’s create our model.

Go to model.py, and you will see that the model class from Django has been imported for you. The below code is used to create the model named Billionaires.

Please take note and the model name is a class that starts with a capital letter.

from django.db import models
from django.urls import reverse

# Create your models here.

class Billionaires(models.Model):
    name = models.CharField(max_length=200, blank=False)
    money = models.IntegerField(blank=False)
    source = models.CharField(max_length=150)
    description = models.TextField()
    
    class Meta:
     ordering = ('-money', )
    
    def __str__(self):
        return "{} is worth ${}billion".format(self.name, self.money)
        
    def get_absolute_url(self):
        return reverse('billionaires')

Let’s dive deep into this model and explain it. 

At the top, I imported models class Django.db and reverse from Django.url, and this is because I want to use the methods and attributes of these classes.

This is the concept of OOP in Python, and you need a working knowledge of it before you understand what is happening here.

I created a class named Billionaires which will inherit from the model class. Then I defined the fields I want in my model. The model name will be the table name, while the fields will form the table’s columns.

Please read the documentation to learn more about these fields to understand what you want to use when creating your fields.

Next, I created a Meta class. The Meta class is the inner class of your model class. Model Meta is used to change your model fields’ behavior like changing order, which is what I did.

I simply asked it to give me a descending order of the money. (This is entirely optional.) essentially asking it to order them according to their worth.

The first function simply instructs Django to display the name and worth of every billionaire in the admin panel.

At the same time, the absolute method is used to reverse to the homepage after updating the app using the referenced name billionaires.

You will soon see how I created this name in the url.py file of the app. Now, it is time to register your models in the admin.py in the same app folder.

# Admin.py

from django.contrib import admin
from .models import Billionaires

# Register your models here.

admin.site.register(Billionaires)

To register the model in your admin, you need to import it into the admin.py file and register it as we did in the last line. Registering a model enables it to show in the admin panel.

After registering the app to the admin.py, go to the main project(richestmen) folder.

Go to settings.py, scroll down to INSTALLED_APPS, then install your new app(billionaires).

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'billionaires',
]

Next, is to go to your terminal, and run:

python manage.py makemigrations

This command will bring out all possible files available for migration, then run:

python manage.py migrate

This command will populate your database with the newly created model(s). You have to do the last two steps whenever there is a change in the models.

After populating your database, head straight to http://127.0.0.1:8000/admin, log in, and create your first billionaire. The data of the billionaire is only true as of August 13th, 2021 from Business Insider

View

Next, we will work on the view.py file. This file is the longest of the files, but do not be intimidated as I will explain everything to you.

# Views.py
from django.shortcuts import render, redirect, reverse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.db.models import Avg, Max, Min, Count
from .models import Billionaires
from .forms import PostForm

# Create your views here.

class BillionairesView(ListView):
    model = Billionaires
    template_name = 'billionaires/chart.html'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['av'] = Billionaires.objects.all().aggregate(Avg('money'), Max('money'), Min('money'), Count('money'))
        return context

To start working on this file, we need to import all the necessary classes and methods. I have explained the reverse in model.py.

Now notice that from Django.views.generic, I imported several views. Yes, I didn’t create them. Django did. This is to make our life so easy. 

Before I explain what they do, I must mention that Django has two ways of getting information from the database. They are called function-based views (FBV) and class-based views (CBV).

The difference between them is simply that, in FBV, you write your function and tell it what to do, while in CBV, Django has done all the heavy lifting for you.

All you need to do is to import them and use them. I am sure you are beginning to say, let’s use the CBV then. Why should I go and create mine when it has been created for me?

As you know, with FBV, you are in control, but with CBV, you control through the help of Django.

Now, I will strongly recommend you start with CBV, understand it before you start learning FBV. CBV is easier if you know what is happening in the background.

Another reason I recommend CBV is that you will need it when you start working with Django Rest Framework to create APIs.

Now that we understand the basics of these views let’s list them below. (these CBVs do what their names say).

ListView:

Lists all the rows in your table.

DetailView:

It gives all the details of an individual row using the primary key(ID) or the slug.

CreateView:

It works with FormView to create the data from the front-facing app.

UpdateView:

 This updates all the rows one at a time. 

DeleteView:

This view deletes all rows one at a time.

Again, please visit Django documentation to get a more detailed understanding of all the methods and classes these views inherited that help them work effectively.

It is about the best docs I have seen out there, followed by MDN JS docs. I will be using some of these methods, attributes, and subclasses, and I will explain them later.

After that, I imported some aggregate functions Django.db.models for my aggregation, which you will see on the homepage. Talking about the home page, I have created a template where all our HTML files will be.

The Django way is to go to the app folder and create a new folder named templates.

Then, inside the templates folder, create another folder named Billionaires. That is the Django way. Don’t worry about how to locate these files.

django folder

Then I imported the Billionaires model from the model and PostForm from forms.py. (Note: I created this file.).

Just hang on tight, and I will explain what is inside.

Let’s start with the ListView.

Here, we want to list all the billionaires on our webpage. So I created BillionairesView, which inherits all the attributes and methods of ListView.

The basic things it needs are the model(Billionaires) and the template directory of the HTML file you want to display. In this case, billionaires/charts.html.

This is all you need to do, and your file will be populated with the list of all the rows in your database table. The additional method is optional. This depends on what you need.

In my case, I needed more data from the database. Hence I use the built-in class that ListView inherited to get my other information. 

Context[‘av’] is how I chose to store all the querysets I am getting from the database. In this case, I requested for Max, Avg, Min, and Count of the money using the aggregate method. Then I returned to context.

A QuerySet is a list of objects of a given Model. QuerySets allow you to read the data from the database, filter it and order it. Below is a basic diagram of how to use querysets in Django.

Now, I need to go to my chart.html and display the data using the context name av. But before I can do that, we need to tell Django how to find the URL of this file.

URL Routing

So Django root project comes with a URL:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('', include('billionaires.urls')),
    # path('authentication/', include('authentication.urls')),
    path('admin/', admin.site.urls),
    
    
]

We can choose to route our app(billionaires) directly to the project URL or set up a new urls.py file in the app(billionaires), then link it to the project file.

This way, there will be a separation of concerns. If I have more than one app, each app will have its urls.py, making it easier to manage the routing.

Django link page

From the project urls.py above, I imported the include function and used it to include the billionaires urls.py file. With this, we are done with this urls.py except if I have a new app.

Now let’s see how the billionaires urls.py is setup:

# Billionaires.urls.py

from django.urls import path
from .views import BillionairesView
urlpatterns = [
    path('', BillionairesView.as_view(), name='billionaires'),
]

I created the urls.py in the billionaire's app, imported the path as I will be using it, and imported BillionairesView from views.py.

Then I added the URL path:

‘ ‘      the empty string means display this HTML file as the index page,

BillionairesView.as_view() is how to indicate that it is a class-based view, and lastly, name=’billionaires’ is the name Django uses to reference the URL of that file (you can name yours anything). I will use the name as a href tag to reference the URL path.

Even if you change the URL pattern, it will not affect the link from working. This is because we are using the name and not the pattern. The name, in turn, references any active pattern at the time.

This is simply the same with ListView. Again, it requires the Model(Billionaires), template_name(‘billionaires/add_bill.html), and an additional information form_class(PostForm).

# Views.py
from django.shortcuts import render, redirect, reverse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.db.models import Avg, Max, Min, Count
from .models import Billionaires
from .forms import PostForm


class CreateBillionaireView(CreateView): 
  
    # specify the model for create view 
    model = Billionaires 
    form_class = PostForm
    template_name = 'billionaires/add_bill.html'
    
    # specify the fields to be displayed 
  
    # fields = ['name', 'money', 'source', 'description']

Form

I created the form class in form.py. This is simple to create. Django has already done the heavy lifting for us. All we need to do is to use it.

Let’s go to form.py:

# Form.py
from django import forms
from .models import Billionaires

class PostForm(forms.ModelForm):
    class Meta:
        model = Billionaires
        fields = ['name', 'money', 'source', 'description']
        widgets = {
            'name' : forms.TextInput(attrs={'class': 'form-control'}),
            'money' : forms.TextInput(attrs={'class': 'form-control'}),
            'source' : forms.TextInput(attrs={'class': 'form-control'}),
            'description' : forms.Textarea(attrs={'class': 'form-control'}),
        }

Here, we imported the forms class, and from models.py, I imported the Billionaires model.

I created a class named PostForm which inherited the ModelForm class in forms. Then I used the Meta class (I have explained this concept in the Model.py section).

When creating the form, I need the model(Billionaires) to specify the field from the Billionaires model I want.

Now, the widgets are Django’s way of making its form look better. I am using Bootstrap, so the class names are Bootstrap classes.

Remember, I can go ahead with my form without the widget. If it is not clear to you, you may ignore the widgets for now.

Please note that, when building Django views, whether it is a CBV or FBV, after each view, you can go ahead and create the route `urls.py` to see if your view is working correctly. We will create all the other routes at the end of the views.

For the UpdateView and DeleteView, you can see that it is the same method.

However, I commented on the area where you can specify the field you want to update. This is optional or based on what you want to update.

from django.shortcuts import render, redirect, reverse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.db.models import Avg, Max, Min, Count
from .models import Billionaires
from .forms import PostForm
      
        
class UpdateBillionaireView(UpdateView):
    # specify the model you want to use
    model = Billionaires 
    template_name = 'billionaires/update_bill.html'
    form_class = PostForm
  
    # specify the fields
    # fields = [
    #     "name",
    #     "money",
    #     "source",
    #     "description"
    # ]
  

   

class DeleteBillionaireView(DeleteView):
    model = Billionaires
    template_name = 'billionaires/confirm_delete.html'

    success_url ="/"

Now, this is how simple the class-based views are. The downside to this method is that it can shield you from learning how things truly work. I will advise that you take your time and understand how these views work under the hood.

Now that we are done using all the views we want to use. Let’s route all the views to the urls.py of the app.

# Billionaires.urls.py
from django.urls import path
from .views import BillionairesView, CreateBillionaireView, UpdateBillionaireView, DeleteBillionaireView

urlpatterns = [
    path('', BillionairesView.as_view(), name='billionaires'),
    path('update/<int:pk>', UpdateBillionaireView.as_view(), name='update'),
    path('add', CreateBillionaireView.as_view(), name='create-bill'),
    
    path('delete/<int:pk>', DeleteBillionaireView.as_view(), name='delete'),
]

Notice how I imported all the views I created from the views.py before creating the path.

Update and delete are slightly different, and this is because these views reference individual rows in the database table. So it references them with their ID, which is by default a primary key.

This ID is auto-created by Django. This is the reason I did not indicate it as a field in my model.

Template

Now it is time to head straight to the template. This is the last part of the Django MVT architecture. It is the user-facing part of the application. Hence it displays the data gotten from the database.

Here, we work with HTML/CSS/Javascript and Django templating language.

The HTML displays static content while the templating language is used to display dynamic content from the views.py. That’s how simple it is.

Earlier, we discussed configuring the template in the settings.py. If you carefully check, you will see that I tend to have two folders named templates.

Let me explain this:

Generally, the templates folder is created in the same level directory as the `manage.py`, and this templates folder can take all the templates you will need for your different Django apps.

These are templates we registered in the settings.py. You may also allow it to house only templates shared among different apps in your project.

The second template found in the app folder of the project is specific to that app. This is the template I refer to as template_name.

If you choose to maintain a template for different apps without general information, you don’t need to register it in the settings.py.

Remember that part of Django’s core function is the principle DRY (Don’t Repeat Yourself). By creating a public template folder at the root level, you are enforcing the DRY principle. 

This is what I did by creating a base.html file in the folder. This will house all the HTML code that will be shared among the different pages of my application.

Django template deals with passing information from views to the browser. This action is known as the basic building block of a dynamic Django application.

Django Templating Language Terminologies

Variable:

It helps get out data from the context. The basic syntax  {{ variable_name }}.

Tags.

These give logic to the templating language. Tags are more powerful than variables. The basic syntax  is {% tag %} 

Some of the places we use tags are:

Control Flow

Load external information into the template

The ones we will be using are:

{%  csrf_token %}
{%  load static  %}
{%  extends base.html %}
{%  block title %}
{%  block scripts %}
{%  block content %}
{%  for x in y %}
{%  if condition %}
{%  else %}
{%  endif %}
{%  include template_name %}
{% url 'some-url-name' v1 v2 %}

The official documentation will do better if you want to learn more about Django templates.

Now, let’s see how we rendered our dynamic content from view into our various HTML files in the templates folder.

We will start with the base.html file. This file contains all the designs and codes we don’t want to repeat. They are Bootstrap CDN, navigation bar, ChartJS CDN, title, scripts, and content blocks.

The way they work is simple: in a normal HTML code structure, we have the <html>, <head> and <body> tags. 

The opening and closing blocks for scripts mean when base.html is extended to any HTML file, that will be the position of javascript. This also is true for opening and closing block content.

At the end of each logic, we prepend the end before the first letter to indicate the end of that block or logic.

Example: to indicate the end of a block title, we end it thus {%  endblock title %} (this does not include csrf_token, extends, and some other tags.

URL with Django Template Tag

Earlier I listed some template tags. One of them is the URL tag.

{% url 'some-url-name' v1 v2 %}

It returns an absolute path referencing a given view and optional parameters. This is how Django output links without violating the DRY principle.

The first argument for some-url-name is the URL pattern name. The other arguments are optional.

<a class="text-decoration-none" href="{% url 'update' item.pk %}">Edit</a>

The code snippet above chart.html has the name update, which corresponds to my name the UpdateView in billionaires.urls.py.

The second is the optional argument `item.pk`, which targets a particular object using its primary key (the auto-generated ID field in the Django model).

The image below will give a clearer understanding of the concept. The reference name is vital if the path changes in the urls.py, the link in the static pages will not break.

Django linking page

The image below will give a clearer understanding of the concept. The reference name is vital if the path changes in the urls.py, the link in the static pages will not break.

Django link page

Implementing the ListView

The first CBV we used was the ListView, where we created BillionairesView. I called the context of this view in chart.html.

{% extends 'base.html' %}

{% block title %} Billionaires Ranking {% endblock title %}

{% block scripts %}
<script>
$(document).ready(function(){
    var ctx = document.getElementById('myChart').getContext('2d');
    var chart = new Chart(ctx, {
    // The type of chart we want to create
    type: 'horizontalBar',

    // The data for our dataset
    data: {
        labels: [{% for item in object_list %}'{{item.name}}',{% endfor %}],
        datasets: [{
            label: 'First 10 Richest Persons On Earth in Billions',
            backgroundColor: 'rgb(0,0,255)',
            borderColor: 'rgb(0,0,255)',
            data: [{% for item in object_list %}{{item.money}},{% endfor %}]
        }]
    },

    // Configuration options go here
    options: {}
});
    });
    
</script>
{% endblock scripts %}

{% block content %}
<div class="container-sm mt-2">
<div class="row">
  <div class="col-sm-3">
    <div class="card">
      <div class="card-body text-center badge bg-primary text-wrap">
      <p class="fs-4"> No. of Billionaires </p>
        <h5 class="card-title">{{ av.money__count }}</h5>
      </div>
    </div>
  </div>
  <div class="col-sm-3">
    <div class="card">
      <div class="card-body text-center badge bg-primary text-wrap">
        <p class="fs-4"> Richest Person  </p>
        <h5 class="card-title">${{ av.money__max }}Billion</h5>
      </div>
    </div>
  </div><div class="col-sm-3">
    <div class="card">
      <div class="card-body text-center badge bg-primary text-wrap">
        <p class="fs-4"> 10th Richest Person </p>
        <h5 class="card-title">${{ av.money__min }}Billion</h5>
      </div>
    </div>
  </div><div class="col-sm-3">
    <div class="card">
      <div class="card-body text-center badge bg-primary text-wrap">
        <p class="fs-4"> Average Worth </p>
        <h5 class="card-title">${{ av.money__avg }}Billion</h5>
      </div>
    </div>
  </div>
</div>
  <div class="row">
  <div class="col-5 mt-4">
<canvas id="myChart" width="200" height="200"></canvas>
</div>

<div class="col-7 mt-4">
      <div class="list-group">
      <button type="button" class="list-group-item list-group-item-action active" aria-current="true">
       List Of Top 10 Billionaires In The World
      </button>
      {% for item in object_list %} 
      <button type="button" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"> {{item.name}} <div class="float-right"> <span class="badge bg-primary squared-pill">${{item.money}}B</span> <small class="badge bg-secondary squared-pill"><a class="text-decoration-none" href="{% url 'update' item.pk %}">Edit</a></small><small class="badge bg-danger  squared-pill"><a class="text-decoration-none" href="{% url 'delete' item.pk %}">Delete</a></small></div></button>
      {% endfor %}
    </div>
</div>

</div>

</div>

{% endblock content %}

Wow!

So much to take in at a time here. It is ok to take a break, refill your coffee and return. We are almost through. 

Next, I have the bar chart rendered through a javascript library called Chartjs. Don’t worry so much about this. I will explain it. Also, notice that the code is between the opening and closing Django scripts tag.

The second is the cards that show the aggregate functions. I enclosed them in the block content. Recall that I stored the context in av.

All I need to use any of the information I am pulling from the database is simply use Django’s template variable in double curly braces, chain it to the field name (‘money’), and double underscores, followed by the aggregate function I want to call. 

This is the Django way. You can see it is consistent in all the calls.

The last on this page was to call all the billionaires’ names and worth. Here I used another Django tag to loop through the list of items and display them. Notice that I didn’t use the stored context name av.

Instead, I used object_list. Yes, this is an inbuilt method that lists all the objects in the database table. If you don’t want to store the data in a context name, you can directly use object_list.

This is it for this file. 

Before we move to another file, let’s discuss briefly Chartjs:

Implementing CHART.JS

Chart.js is simple, clean, and engaging HTML5 based JavaScript Charts. Chart.js is an easy way to include animated, interactive graphs on your website for free. The beautiful thing about this is that it is a plug-and-play library. 

Recall that I linked the CDN in the base.html. That’s how simple it is to set up. Next is to plug in the data from the views.py, and you are good to go.

<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        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)'
        }]
    },
    options: {}
});
});
</script>

This is a simple structure of the ChartJS library. It works with HTML canvas. We declare the canvas in any part of the page with id=myChart or any name you prefer.

From the code below, we have a javascript object named data. Inside it are arrays. The arrays are labels and datasets. (This is Javascripts, I will advise that you just plug in the data as I did.

You may make out time to learn Javascripts) clear the dummy data and write your logic as below:

data: {
        labels: [{% for item in object_list %}'{{item.name}}',{% endfor %}],
        datasets: [{
            label: 'First 10 Richest Persons On Earth in Billions',
            backgroundColor: 'rgb(0,0,255)',
            borderColor: 'rgb(0,0,255)',
            data: [{% for item in object_list %}{{item.money}},{% endfor %}]
        }]
    },

In the labels, I looped through the object-list, called the name({{item.name}}), and ended the loop.

I did the same in the data. This time, I called the money. Then I chose my type of chart as horizontalBar. There are other charts, just change the name and see the chart you prefer.

This is all you need to do, and your chart will populate on your page.

For more on Chart.js, please visit the documentation. It is easy to use. A little knowledge of Javascript is required to understand it fully.

Implementing the CreateView

The next CBV is the CreateView, which we name as CreateBillionaireView. Since this is a POST request, we will work with add_bill.html.

The code is below:

{% extends 'base.html' %}
{% block title %}A New Billionaire{% endblock title %}

{% block content %}
<div class="container-sm mt-2 col-4">
<h3>Add A New Billionaire</h3>
<div class="form-group">
<form method="POST" enctype="multipart/form-data"> 
  
    <!-- Security token -->
    {% csrf_token %} 
  
    <!-- Using the formset -->
    {{ form.as_p }} 
      
    <input class="btn btn-secondary" type="submit" value="Submit"> 
</form> 
</div>
</div>

{% endblock %}

Again, I extended the structure of base.html, the title block, and the content block. Inside the block content, I created a form tag.

Inside the tag, I have the csrf_token (CSRF stands for Cross-Site Request Forgery) to avoid CSRF attacks. Please read it for more information. Then I brought in the Django inbuilt form form.as_p.

That is all.

Note: form.as_p means display the form as a paragraph tag. you may choose to display as an h4 tag as follows “form.as_h4”.

Django will populate your form based on the fields you selected in your form.py file if you do that.

Next in line is the UpdateView. Here I have the update_bill.html for the update, and this is just like the add_bill.html.

{% extends 'base.html' %}
{% block title %}Update Billionaires List{% endblock title %}

{% block content %}
<div class="container-sm mt-2 col-4">
<h3>Update Billionaires List {{ bn.name }}</h3>
<div class="form-group">
<form method="POST" enctype="multipart/form-data"> 
  
    <!-- Security token -->
    {% csrf_token %} 
  
    <!-- Using the formset -->
    {{ form.as_p }} 
      
    <input class="btn btn-secondary" type="submit" value="Update"> 
</form> 
</div>
</div>

{% endblock content %}

 Next is to confirm it on the confirm page. confirm_update.html
{% extends 'base.html' %}
{% block title %}Update Billionaires List{% endblock title %}

{% block content %}
<div class="container-sm mt-2 col-4">
<h3>Update Billionaires List {{ bn.name }}</h3>
<div class="form-group">
    <a href="{% url 'update' billionaires.id %}"><button type="button" class="list-group-item list-group-item-action active" aria-current="true"></button></a>
</div>
</div>

{% endblock content %}

Finally, in the views directory is the DeleteView. All I need is the confirm delete page since the delete button is linked on the home page (chart.html).

{% extends 'base.html' %}
{% block title %}Confirm Billionaires Delete{% endblock title %}

{% block content %}
<div class="container-sm mt-2 col-4">
<h1>Confirm Billionaires Delete</h1>
<div class="form-group">
<form method="POST" enctype="multipart/form-data"> 
  
    <!-- Security token -->
    {% csrf_token %} 
  
  Are you sure you want to delete this billionaire?
      
    <input class="btn btn-secondary" type="submit" value="Delete"> 
</form> 
</div>
</div>

{% endblock %}

Here, all the magic has been taken care of by Django through the DeleteView. Just create a form tag with a post method and include the csrf_token.

This is the end of the template part of the MVT architecture.

Conclusion

This article explains the fundamentals of creating an application with Django using Django class-based views, MySQL database, Chart.js and deployed to Heroku.

As stated, it is just a simple application. You can further expand on it by creating authentication and authorization. You may also think of uploading a CSV file that contains more billionaires to expand the list instead of manually creating them yourself.

The list of things to do is endless. I encourage you to do more, make mistakes, learn from them and become better. There is no alternative to becoming perfect except by practice.

Let me know in the comment if you have any challenges, and we will fix them together. Thank you

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Backend Tips, Every week

Backend Tips, Every week