abautista
abautista

Reputation: 2780

How to successfully pass a Json to render and manipulate it in Django?

I am trying to return a Json response from a POST request but I am encountering various errors in the path.

First, I have the following view

class ChartData8(APIView):
    def tickets_per_day_results(request):
        if request.method == "POST":
            template_name = 'personal_website/tickets_per_day_results.html'
            year = request.POST.get('select_year', None)
            week = request.POST.get('select_week', None)
            ....do stuff...
            data = {"label_number_days": label_number_days,
                    "days_of_data": count_of_days}
        return render(request,template_name,JsonResponse(data))

that calls the template tickets_per_day_results.html which contains an Ajax request:

$.ajax({
    method: "POST",
    url: endpoint,
    dataType: 'json',
    contentType: "application/json",
    headers: {"X-CSRFToken": $.cookie("csrftoken")},
    success: function(data){
        console.log(data)
        label_number_days = data.label_number_days
        days_of_data = data.days_of_data
        setChart()

    },
    error: function(jqXHR,error_data, errorThrown){
        console.log("error on data")
        console.log(error_data)
        console.log(JSON.stringify(jqXHR))
        console.log("AJAX error: " + error_data + ' : ' + errorThrown)
    }

but this combination throws me context must be a dict rather than JsonResponse error.

I tried various alternatives:

Alternative 1: Instead of JsonResponse I used Response like the following:

class ChartData8(APIView):
    def tickets_per_day_results(request):
        if request.method == "POST":
            template_name = 'personal_website/tickets_per_day_results.html'
            year = request.POST.get('select_year', None)
            week = request.POST.get('select_week', None)
            ....do stuff...
            data = {"label_number_days": label_number_days,
                    "days_of_data": count_of_days}
        return render(request,template_name,Response(data))

but this threw out the error context must be a dict rather than Response.

Alternative 2: Instead of JsonResponse and Response I tried to convert the object to a dict like the following:

class ChartData8(APIView):
    def tickets_per_day_results(request):
        if request.method == "POST":
            template_name = 'personal_website/tickets_per_day_results.html'
            year = request.POST.get('select_year', None)
            week = request.POST.get('select_week', None)
            ....do stuff...
            data = {"label_number_days": label_number_days,
                    "days_of_data": count_of_days}
        return render(request,template_name, dict(Response(data)))

but this threw out the error The response content must be rendered before it can be iterated over.

Alternative 3: Instead of 1 and 2 I tried to pass data without JsonResponse nor Response:

class ChartData8(APIView):
    def tickets_per_day_results(request):
        if request.method == "POST":
            template_name = 'personal_website/tickets_per_day_results.html'
            year = request.POST.get('select_year', None)
            week = request.POST.get('select_week', None)
            ....do stuff...
            data = {"label_number_days": label_number_days,
                    "days_of_data": count_of_days}
        return render(request,template_name, data)

but this threw out the error parsererror from the ajax request because this means you simply return a string or another value, it is not really Json, so the parser fails when parsing it. You can avoid this error by removing dataType:'json' from the Ajax request (solution from parsererror Ajax) but this will not allow me to manipulate my datasets from my template tickets_per_day_results, that is,

remove dataType:json

$.ajax({
    method: "POST",
    url: endpoint,
    headers: {"X-CSRFToken": $.cookie("csrftoken")},
    success: function(data){
        console.log(data)
        label_number_days = data.label_number_days
        days_of_data = data.days_of_data
        setChart()

    },
    error: function(jqXHR,error_data, errorThrown){
        console.log("error on data")
        console.log(error_data)
        console.log(JSON.stringify(jqXHR))
        console.log("AJAX error: " + error_data + ' : ' + errorThrown)
    }

then I cannot manipulate my datasets that are found below the Ajax request:

data: {
        labels: label_number_days,
        datasets :
            [{
                label: 'User_001',
                data [days_of_data[0],days_of_data[1],days_of_data[2],days_of_data[3],days_of_data[4],days_of_data[5],days_of_data[6]],
                backgroundColor: 'rgba(255, 99, 132, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

because you found Uncaught TypeError: Cannot read property '0' of undefined.

This has been a tedious path and I am running out of ideas (and patience). If anyone can suggest me any other alternative then that will give me some health relief.

Update Tickets per day results html file

{% extends "personal_website/header.html"%}

<script>
{% block jquery %}

var endpoint = '/tickets_per_day_results/' //This works with the chart_data view.

var days_of_data = []
var label_number_days = []

$.ajax({
    method: "POST",
    url: endpoint,
    dataType: 'json',
    contentType: "application/json",
    headers: {"X-CSRFToken": $.cookie("csrftoken")},
    success: function(data){
        console.log(data)
        label_number_days = data.label_number_days
        days_of_data = data.days_of_data
        setChart()

    },
    error: function(jqXHR,error_data, errorThrown){
        console.log("error on data")
        console.log(error_data)
        console.log(JSON.stringify(jqXHR))
        console.log("AJAX error: " + error_data + ' : ' + errorThrown)
    }
})
function setChart()
{var ctx_tickets_per_day       = document.getElementById("tickets_per_day")

var tickets_per_day = new Chart(ctx_tickets_per_day, {
    showTooltips: false,
    type:'bar',
    data: {
        labels: label_number_days,
        datasets :
            [{
                label: 'Oscar Gil',
                data: [days_of_data[0],days_of_data[1],days_of_data[2],days_of_data[3],days_of_data[4],days_of_data[5],days_of_data[6]],
                backgroundColor: 'rgba(255, 99, 132, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },
            {
                label: 'Oscar Rodriguez',
                data: [days_of_data[7],days_of_data[8],days_of_data[9],days_of_data[10],days_of_data[11],days_of_data[12],days_of_data[13]],
                backgroundColor: 'rgba(54, 162, 235, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Animesh Rathore',
                data: [days_of_data[14],days_of_data[15],days_of_data[16],days_of_data[17],days_of_data[18],days_of_data[19],days_of_data[20]],
                backgroundColor: 'rgba(255, 206, 86, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Bhaskar Sharma',
                data: [days_of_data[21],days_of_data[22],days_of_data[23],days_of_data[24],days_of_data[25],days_of_data[26],days_of_data[27]],
                backgroundColor: 'rgba(75, 192, 192, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Victor Catacora',
                data: [days_of_data[28],days_of_data[29],days_of_data[30],days_of_data[31],days_of_data[32],days_of_data[33],days_of_data[34]],
                backgroundColor: 'rgba(153, 102, 255, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Jimmy Gonzalez',
                data: [days_of_data[35],days_of_data[36],days_of_data[37],days_of_data[38],days_of_data[39],days_of_data[40],days_of_data[41]],
                backgroundColor: 'rgba(236, 115, 9, 1)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Piyush Gupta',
                data: [days_of_data[42],days_of_data[43],days_of_data[44],days_of_data[45],days_of_data[46],days_of_data[47],days_of_data[48]],
                backgroundColor: 'rgba(185, 29, 12, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Carlos Prieto',
                data: [days_of_data[49],days_of_data[50],days_of_data[51],days_of_data[52],days_of_data[53],days_of_data[54],days_of_data[55]],
                backgroundColor: 'rgba(105, 129, 64, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            {
                label: 'Daniel Estrada',
                data: [days_of_data[56],days_of_data[57],days_of_data[58],days_of_data[59],days_of_data[60],days_of_data[61],days_of_data[62]],
                backgroundColor: 'rgba(15,  199, 84, 0.6)',
                borderColor: '#777',
                borderWidth: 1,
                hoverBorderWidth: 3,
                hoverBorderColor: '#000'
            },

            ]
        },
        options: {
          scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
          },

          title: {
            display: true,
            text: 'Tickets by engineer per day',
            fontSize: 30
            },
        legend: {
            position: 'right',
            display: true,
            labels: {
                fontColor: '#000'
                }
            },
            layout: {
                padding: {
                    left: 50,
                    right: 0,
                    bottom: 0,
                    top: 0
                    }
            },
            tooltips: {
              enabled: true
            },

          hover : {
            animationDuration: 0
          },

          animation: {
            duration: 0.8,
            onComplete: function(){
                var chartInstance = this.chart,
                ctx = chartInstance.ctx;
                Chart.defaults.global.defaultFontColor = '#777';
                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize,
                           Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset, i) {
                var isHidden = dataset._meta[0].hidden; //'hidden' property of dataset
                if (!isHidden) { //if dataset is not hidden
                    var meta = chartInstance.controller.getDatasetMeta(i);
                    meta.data.forEach(function (bar, index) {
                        var data = dataset.data[index];
                        ctx.fillText(data, bar._model.x, bar._model.y - 5);});
                    }});
            }
          }
        }
    })
}

{% endblock %}

    {% block content %}

<div class ='row'>

    {% csrf_token %}
<div class="col-sm-12" url-endpoint='{% url "tickets_per_day_results" %}'>
        <div>
            <canvas id="tickets_per_day" width="800" height="500"></canvas>
        </div>
</div>
</div>
 {% endblock content %}

Upvotes: 0

Views: 405

Answers (1)

Dronix
Dronix

Reputation: 26

I think that you're using the wrong method for returning data in JSON format. In the code :

render(request,template_name,JsonResponse(data))

In the documentation of Django here. The render shortcut is used to render an Html Template with dictionary data to update the page.

According to the django code I guess you use Django rest Framework. In order to send JSON data you should use the example here DRF example response in order to send JSON data to the page.

Upvotes: 1

Related Questions