Add Charts To Visualize Your Django Polling-App Data

Polling apps are a great way to engage your users and get valuable insights into their opinions and preferences. With Django, you can create a robust polling app with minimal effort. Writing your first Django app tutorial gives you a clear idea about creating a simple polling app in Django. In this article, let's see how to visualize the polling result as charts using CanvasJS Python Charts.

Before diving in, let's look at what CanvasJS is. CanvasJS is a powerful and customizable charting library that allows you to create interactive and responsive charts for web applications. It supports various chart types like column charts, pie charts, bar charts, line charts, and more.

Django Polling App

Prerequisite

Project Setup & New App

The first step is to create a new Django project and app. Follow the Writing your first Django app tutorial for a step-by-step guide to creating an app & steps to store poll data in the database.

Define the Models

Create models for our app. In models.py, create Datapoints model along with existing Question & Choice models. The datapoints model will represent the chart datapoints, whereas the Question and Choice models will represent the question the user can answer and the options for each question, respectively.

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('Date Published')

    objects = QuestionManager

    class Meta:
        unique_together = [['question_text']]

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

class DataPoint(models.Model):
    x = models.IntegerField()
    y = models.IntegerField()
    label = models.CharField(max_length=200, default="")

Create the views

Now that the models are defined create the views for displaying the list of polls, displaying details of a specific poll, and handling the user votes.

from django.http import HttpResponse, HttpResponseRedirect
from django.template import loader
from django.shortcuts import render, get_object_or_404
from django.http import Http404
from django.urls import reverse
from django.views import generic
from django.core import serializers
import random

from .models import Question, Choice, DataPoint

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        questions = Question.objects.order_by('pub_date')[:5]
        context = []
        for question in questions:
            context.append({ 'question': question, 'choice_list': serializers.serialize("json", question.choice_set.all())})
        return context

class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return list(context)    

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

Create the templates & add CanvasJS

Create templates for displaying the list of polls, specific poll details, and result. Listing the polls and details of a particular poll is already briefed in the Django Creating first app tutorial. To make our polling app more visually appealing, let's add CanvasJS charts to show the poll results in the form of charts. Install CanvasJS in the results template.

<script src="https://canvasjs.com.assets/script/canvasjs.min.js"></script>
 <!-- or -->
<script src="{% static 'js/canvasjs.min.js' %}"></script>

Let's add Python Bar Chart to show the result of the poll. To do so, place the chart-container div in the HTML container where you like to show the chart. Get the poll result and iterate through it to generate datapoints for the CanvasJS library. Call chart.render() method once you pass the datapoints in the chart options.

<div id="chartContainer" style="height: 400px; width: 100%;"></div>

<script type="text/javascript">
var jsonData = {{ choice_list|safe }};

window.onload = function() {
	var dps = [];
	jsonData.forEach(data => {
		dps.push({label: data.fields.choice_text, y: data.fields.votes})
	});

	var chart = new CanvasJS.Chart("chartContainer", {
		animationEnabled: true,
		theme: "light2",
		axisX: {
			reversed: true
		},
		data: [{
			type: "bar",
			indexLabel: "{y}",
			dataPoints: dps
		}]
	});
	chart.render();
};
</script>

Update the views to include the chart visualization. Add a new view called results that retrieves specific poll data & passes it to the results.html template.

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question, 'choice_list': serializers.serialize("json", question.choice_set.all())})

Django Polling App Visualization using CanvasJS Charts

And that's it! We've successfully added charts to visualize the poll results in a Django polling app. Admins can create new polls. Users can vote on existing polls and view the vote distribution for each poll in the form of a bar chart.


Similar Articles