Passing data from views.py to chartjs

I’m total noob to chartjs, and quite a noob to Django. I managed to grab data from db and display it in a template, but I want to display the data as a chart so I added chartjs. It works.

Now I want to apply custom colors to a chart accordingly to conditions, and I’m stuck and need help.

I have a model

from django.db import models

class Record(models.Model):

    user = models.CharField(max_length=50)
    creation_date = models.DateTimeField(auto_now_add=True)
    sis = models.PositiveSmallIntegerField()
    dia = models.PositiveSmallIntegerField()
    pulse = models.PositiveSmallIntegerField()
    diff = models.PositiveSmallIntegerField(blank=True, null=True)

    def __str__(self):
        return str(self.creation_date) + "   " + str(self.user) + "   " + str(self.sis) + "   " + str(self.dia) + "   " + str(self.pulse) + "   " + str(self.diff)

I grab the data for the last 7 days

def index(request):
    last_days = now() - timedelta(days=7)
    records = Record.objects.filter(user=request.user, creation_date__gte=last_days).annotate(day=TruncDate('creation_date')).values('day').annotate(max_sis=Max('sis'), min_sis=Min('sis'), max_dia=Max('dia'), min_dia=Min('dia'), max_diff=Max('diff'), min_diff=Min('diff'), max_pulse=Max('pulse'), min_pulse=Min('pulse')).order_by('day')

    return render(request, 'core/index.html', {'records': records})

and I pass to chartjs in a template like this:

    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

    <script>
        const ctx = document.getElementById('myChart');

        new Chart(ctx, {
            type: 'bar',
            data: {
                labels: [{% for record in records %}'{{ record.day|date:"d/m" }}',{% endfor %}],
            datasets: [{
                label: 'Sis',
                data: [{% for record in records %}{{ record.max_sis }}, {% endfor %}],
            backgroundColor: 'green',
            borderWidth: 1
                },
            {
                label: 'Dia',
                data: [{% for record in records %}{{ record.max_dia }}, {% endfor %}],
            backgroundColor: 'blue',
            borderWidth: 1
            }]
            },
            options: {
            scales: {
                y: {
                    beginAtZero: true
                }
            }
        }
        });
    </script>

It works.
Now I want the background color for ‘Sis’ to be not always green, but when it’s < 130, and above 130 - yellow. So I decided that in theory I can do it. I added to a view few lines of code to create a list of colors and passed it to chartjs, but the chart doesn’t display.

modified view

def index(request):
    last_days = now() - timedelta(days=7)
    records = Record.objects.filter(user=request.user, creation_date__gte=last_days).annotate(day=TruncDate('creation_date')).values('day').annotate(max_sis=Max('sis'), min_sis=Min('sis'), max_dia=Max('dia'), min_dia=Min('dia'), max_diff=Max('diff'), min_diff=Min('diff'), max_pulse=Max('pulse'), min_pulse=Min('pulse')).order_by('day')
    bg_sis = []
    
    for record in records:
        if record['max_sis'] < 130:
            bg_sis.append('green')
        else:
            bg_sis.append('yellow')

    return render(request, 'core/index.html', {'records': records, 'bg_sis':bg_sis})

modified chartjs

<script>
        const ctx = document.getElementById('myChart');

        new Chart(ctx, {
            type: 'bar',
            data: {
                labels: [{% for record in records %}'{{ record.day|date:"d/m" }}',{% endfor %}],
            datasets: [{
                label: 'Sis',
                data: [{% for record in records %}{{ record.max_sis }}, {% endfor %}],
            backgroundColor: [{% for mybg in bg_sis %}'{{ mybg }}', {% endfor %}],
        borderWidth: 1
                },
        {
            label: 'Dia',
                data: [{% for record in records %} { { record.max_dia } }, {% endfor %}],
        backgroundColor: 'blue',
            borderWidth: 1
            }]
            },
        options: {
            scales: {
                y: {
                    beginAtZero: true
                }
            }
        }
        });
    </script>

Please help.

Also if I put hardcoded array of colors like this, it works

backgroundColor: ['green', 'yellow', 'green', 'green', 'yellow', 'yellow', 'red',],

but it doesn’t when I pass an array (

{% for mybg in bg_sis %}'{{ mybg }}', {% endfor %}

Can you show a bit more of the JavaScript that’s around this:

Also, what are the errors, if any, showing in your browser’s web development Console?

Never mind. I figured it out. My VSCode auto format on save was braking the js code.

Well done, glad you worked it out.

You might find this post useful. How to Safely Pass Data to JavaScript in a Django Template - Adam Johnson I’ve used the json_script method myself for passing data into chart.js.

1 Like