Django and Chart.js Not Rendering Graph Correctly

試著忘記壹切 提交于 2021-01-29 09:01:23

问题


So I spent the weekend testing and searching SO and finally got Django and Chart.js working. Kind of. It renders the graph but the data is not correct. When I loop through the object, the results are not what I would expect. Maybe I'm blind from staring at this all weekend. Would appreciate any pointers.

Here are my views...

class ChartView(LoginRequiredMixin, TemplateView):
    template_name = 'Books/chart.html'

    def get_context_data(self, **kwargs):
        context = super(ChartView, self).get_context_data(**kwargs)
        qs1 = Class.objects.filter(id__in=self.request.user.userprofile.class.all()).order_by('id')
        qs2 = Books.objects.filter(class__in=self.request.user.userprofile.books.all()).distinct()
        context['qs1'] = qs1
        context['qs2'] = qs2
        return context

class ChartData(LoginRequiredMixin,APIView):
    model = Books
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        qs_count = Books.objects.filter(class__in=self.request.user.userprofile.class.all()).count()
        labels = []
        default_items = []
        data = {
            "labels": labels,
            "default": default_items,
        }
        return Response(data)

Here's my HTML with the Javascript...

{% extends 'base5.html' %}

{% block body_block %}
<div class="box6">
          <h1 class="title">Number of Books By Class</h1>
<canvas id="myChart"></canvas>
<div>

<script>
var endpoint = '{% url "Books:chart_data" %}'
var defaultData = [];
var labels = [];
$.ajax({
    method: "GET",
    credentials: 'same-origin',
    url: endpoint,
    success: function(data){
        labels = data.labels
        defaultData = data.default
        var ctx = document.getElementById("myChart");
        var myChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: [{% for i in qs1 %}{{ i.id }},{% endfor %}],
                datasets: [{
                    label: "# of Books",
                     data: [{% for j in qs2 %}
                              {{ j.id }},
                            {% endfor %}],
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(255, 159, 64, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255,99,132,1)',
                        'rgba(255,99,132,1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'
                    ],
                    borderWidth: 1
                }]
            }
        })
    },
    error: function(error_data){
        console.log("error")
        console.log(error_data)
    }
})
</script>

{% endblock %}

Here are the models.

class Books(models.Model):

    book_name = models.CharField(max_length=80,null=True)
    description = models.TextField(max_length=264,unique=False)
    class = models.ForeignKey(Class,on_delete=models.DO_NOTHING,related_name='classes')

class Class(models.Model):
    class_name = models.CharField(max_length=264,unique=True)
    teacher = models.ForeignKey(User,null=True,
                    on_delete=models.CASCADE,related_name="teacher_name")

I feel like my looping logic in qs2 is where the problem is. It is not properly looping through qs2, as it is returning results, but not the proper ones. I'm only trying to get the books out of the the user that match the class, and it's not working. Also, I can only get the "ID" to display on the graph, not the actual foreign key name. I can't figure out how to get the actual foreign key name to display either. Appreciate any help or pointers as to what I'm doing incorrectly. I'm so close!


回答1:


Try this:

def get_context_data(self, **kwargs):
    context = super(ChartView, self).get_context_data(**kwargs)
    qs1 = Class.objects.filter(id__in=self.request.user.userprofile.class.all()).order_by('id')        
    class_names = [ cls.class_name for cls in qs1]
    books_count = [ Books.objects.filter(class=cls).count() for cls in qs1 ]
    context['qs1'] = class_names
    context['qs2'] = books_count
    return context

Here i want both the Class and Books queryset to be ordered by class because the order is crucial. Here in the context i inject the Class names and Books count directly in the context.

Use This srcipt in the template:

<script>
        var labels = "{{ qs1 }}";
        var ctx = document.getElementById("myChart");
        var myChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: Array.from(labels),
                datasets: [{
                    label: "# of Books",
                     data: [{% for j in qs2 %}
                              {{ j }},
                            {% endfor %}],
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(255, 159, 64, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255,99,132,1)',
                        'rgba(255,99,132,1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'
                    ],
                    borderWidth: 1
                }]
            }
        })
    },
    error: function(error_data){
        console.log("error")
        console.log(error_data)
    }
})
</script>

There is no need for ajax request you already got the data from the context

I hope this will work.




回答2:


After working all day with Yusef BH, came to the following solution regarding rendering the data correctly. Of note is that the labels are still not coming through. I have opened up a separate SO issue for the labels. Here is the code that allowed me to display the items correctly on the graph.

My HTML

{% extends 'base5.html' %}

{% block body_block %}
<div class="box6">
          <h1 class="title">Number of Books By Author</h1>
<canvas id="myChart"></canvas>
<div>

  <script>
  var endpoint = '{% url "Books:chart_data" %}'
  var defaultData = [];
  var labels = [];
  array = {{ procedures3 }}
  $.ajax({
      method: "GET",
      credentials: 'same-origin',
      url: endpoint,
      success: function(data){
          defaultData = data.default
          var ctx = document.getElementById("myChart");
          var myChart = new Chart(ctx, {
              type: 'bar',
              data: {
                  labels: [{% for i in book %}{{ i.id }},{% endfor %}],
                  datasets: [{
                      label: "# of Procedures",
                      data: [{% for j in book_count %}
                               {{ j }},
                             {% endfor %}],
                      backgroundColor: [
                          'rgba(255, 99, 132, 0.2)',
                          'rgba(255, 99, 132, 0.2)',
                          'rgba(54, 162, 235, 0.2)',
                          'rgba(255, 206, 86, 0.2)',
                          'rgba(75, 192, 192, 0.2)',
                          'rgba(153, 102, 255, 0.2)',
                          'rgba(255, 159, 64, 0.2)'
                      ],
                      borderColor: [
                          'rgba(255,99,132,1)',
                          'rgba(255,99,132,1)',
                          'rgba(54, 162, 235, 1)',
                          'rgba(255, 206, 86, 1)',
                          'rgba(75, 192, 192, 1)',
                          'rgba(153, 102, 255, 1)',
                          'rgba(255, 159, 64, 1)'
                      ],
                      borderWidth: 1
                  }]
              }
          })
      },
      error: function(error_data){
          console.log("error")
          console.log(error_data)
      },
  })
  </script>
  {% endblock %}

Views.py

ChartView

class ChartData(LoginRequiredMixin,APIView):
    model = Author
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        default_items = []
        labels = []
        data = {
            "labels": labels,
            "default": default_items,
        }
        return Response(data)

The ChartView

class ChartView(LoginRequiredMixin, TemplateView): template_name = 'Book/chart.html'

def get_context_data(self, **kwargs):
    context = super(ChartView, self).get_context_data(**kwargs)
    book = Author.objects.filter(id__in=self.request.user.userprofile.author.all()).order_by('id')
    books_count = [ Book.objects.filter(author=cls).count() for cls in book ]
    context['book'] = book
    context['book_count'] = books_count
    return context


来源:https://stackoverflow.com/questions/51026703/django-and-chart-js-not-rendering-graph-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!