Labels attribute of chartsjs not taking context variable of type string

Viewed 172

I have a chartsJS chart in my django site. I am using context variables to pass values from my main.py file to the showdata.html via views.py in order to populate the graph. the process goes like this:

  • Main.py

     myList = [T1_sum, T2_sum, T3_sum, T4_sum, T5_sum, T6_sum, T7_sum, T8_sum, T9_sum, T10_sum] 
     mylables = ["T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8", "T9", "T10"]
     sortedlist, sortedlables = zip(*sorted(zip(myList, mylables), reverse=True))
     sortedlist = list(sortedlist)
     sortedlables = list(sortedlables)
    

views.py

def showdata(request):
import json
numbers_in_sModel = sModel.objects.all()
numbers_in_sortedList = MyModel.objects.all()
labels_in_sortedList = myModelSortedLabels.objects.all()

if request.session.get('stats',False):
    js_object = json.loads(request.session.get('stats'))


return render(request, "showdata.html", context={
'numbers_in_sModel':numbers_in_sModel,
'numbers_in_sortedList':numbers_in_sortedList,
'labels_in_sortedList':labels_in_sortedList
})

Showdata.html

var myChart = new Chart(ctx, {
                    type: 'horizontalBar',
                    data: {
                        labels: [
                                        {% for number in numbers_in_sortedList %}
                                        {% for value in number.jsonM %}
                                            {{ value }},
                                        {% endfor %}
                                    {% endfor %}
                        ],
                        datasets: [{
                            axis: 'y',
                            label: false,
                            data: [
                                    {% for number in numbers_in_sortedList %}
                                        {% for value in number.jsonM %}
                                            {{ value }},
                                        {% endfor %}
                                    {% endfor %}
                            ],
                            backgroundColor: ['#36CAAB', '#36CAAB', '#36CAAB', '#36CAAB', '#36CAAB','#36CAAB', '#36CAAB', '#36CAAB', '#36CAAB', '#36CAAB'],
                            borderWidth: 1
                        }]
                    },

Okay above code works to populate the chartsjs graph using the context variables. what is produced is a graph with see below in the picture. The labels of this graph are numbers. as seen in the picture. However what i am trying to do is to replace labels with the sorted labels list. Now the following code works to present the data on the showdata.html page if I put it in tags like etc. so i know the context variables are being passed. however when I place the following code in the labels section of chartsjs it does not present the label values in the graph.

{% for number in labels_in_sortedList %}
 {% for value in number.jsonSortedLabels %}
   {{ value }},
   {% endfor %}
   {% endfor %}

The funny thing is the when i inspection page i see the values in the labels section that should be there except there is an error on the very first label entry saying:

Uncaught ReferenceError: T9 is not defined

enter image description here

4 Answers

I have had this exact problem. Javascript is treating your T1, T2, T3 etc. as variables. Use this instead:

var label_lst = [];
{% for number in labels_in_sortedList %}
{% for value in number.jsonSortedLabels %}
label_lst.push("{{ value }}");
{% endfor %}
{% endfor %}

Then, put your labels key as label_lst:

type: 'horizontalBar',
                    data: {
                        labels: label_lst;
...

it is evaluating your labels as variables, format it into a string with

{% for number in labels_in_sortedList %}
 {% for value in number.jsonSortedLabels %}
   {{ `${value}` }},
 {% endfor %}
{% endfor %}

you should add if statement to check whether it is null or not.

{% if len(numbers_in_sortedList) != 0 %}
  {% for number in numbers_in_sortedList %}
    {% if len(number.jsonM) != 0 %}
      {% for value in number.jsonM %}
        {{ value }},
      {% endfor %}
    {% endif %}
  {% endfor %}
{% endif %}

It looks like the values need to be quoted so as to be treated as strings. The resultant JavaScript array from:

{% for number in labels_in_sortedList %}
    {% for value in number.jsonSortedLabels %}
        {{ value }},
    {% endfor %}
{% endfor %}

possibly looks like:

[T1, T2, ...]

It should look like:

["T1", "T2", ...]

I don't know Django, but presumably you can do this:

{{'"' + value + '"'}},

Edit:

Skimming the Django documentation suggests that "variables" (using {{ and }}) simply output values.

Perhaps using "tags" will work, as "Tags provide arbitrary logic in the rendering process" and also "a tag can output content":

{% '"' + value + '"' %},

Or maybe this would work but my naive assumption is that it will be output as a string literal:

"{{ value }}",
Related