【问题标题】:Django how to send array to JavaScript for dynamically display pie chart?Django 如何将数组发送到 JavaScript 以动态显示饼图?
【发布时间】:2021-10-24 03:25:31
【问题描述】:

我在 Django views.py 中有一个数组,我想将它发送到 HTML 并显示一个饼图,但是 失败了,我尝试了很多其他方法并阅读了很多教程,在大多数情况下,他们有 模型中存储一些数字的字段,它们会显示这些数字。就我而言,我需要 计算处于不同状态的任务的小计。我不确定如何输出这些 如果有任何建议,请使用适当的标签或任何其他饼图将数据发送到 chart.js?

views.py

def visualisation(request, project_id):
    
    project = Project.objects.get(id=project_id)
   
    counts_data = Todo.objects.aggregate(
        to_do_count=Count('id', filter=Q(status='to_do')),
        in_progress_count=Count('id', filter=Q(status='in_progress')),
        done_count=Count('id', filter=Q(status='done'))
        )

    
    return render(request, 'todo_lists/progress.html', {"counts_data": counts_data})

html


<script>
 
$(document).ready(function() {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
    labels: [1,2,3],
    
    datasets: [{
        label: '# of Votes',

        data:{{counts_data}},
        
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)'
        ],
        borderColor: [
            'rgba(255, 99, 132, 1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)'
        ],
        borderWidth: 1
    }]
},
options: {
    responsive:false
    
}
});
});
</script>

【问题讨论】:

  • 只需创建一个对象以将数组存储在javascript中:var obj = {{counts_data}};。并使用该对象的值创建饼图。
  • @AjayLingayat 感谢您的帮助,我试过了,但还是不行,还有其他想法吗?
  • @NikiGrey 请在data:{{counts_data}} 行显示渲染数据。

标签: javascript python django


【解决方案1】:

您需要以结构化方式为 chart.js 获取数据
图表 JS 数据结构 https://www.chartjs.org/docs/latest/general/data-structures.html
您可以简单地遵循如下所示的 Primitive 结构,也可以遵循具有自定义属性的 Object 结构(需要进行进一步的数据格式化和解析)。

    $(document).ready(function() {
        var ctx = document.getElementById('myChart').getContext('2d');
        var myChart = new Chart(ctx, {
            type: 'doughnut',
            data: {
                // labels format ['label1', 'label2', 'label3', ]
                // you can choose to have a static labels if you are sure that 
                // there is always a specific number of labels
                labels: [{% for label in counts_data %} '{{ label }}', {% endfor %}],

                datasets: [{
                    label: '# of Votes',

                    // data format [value1, value2, value3, ]
                    data: [{% for label, value in counts_data.items() %} {{ value }}, {% endfor %}],

                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255, 99, 132, 1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)'
                    ],
                    borderWidth: 1
                }]
            },
            options: {
                responsive: false

            }
        });
    }); 

在您看来,Todo.objects.aggregate(...) 应该返回类似这样的内容(值作为示例提供):

{'to_do_count': 3, 'in_progress_count': 6, 'done_count': 1}

    counts_data = Todo.objects.aggregate(
        to_do_count=Count('id', filter=Q(status='to_do')),
        in_progress_count=Count('id', filter=Q(status='in_progress')),
        done_count=Count('id', filter=Q(status='done'))
        )
    # counts_data = {'to_do_count': 3, 'in_progress_count': 6, 'done_count': 1}

这个字典然后被传递给上下文,其键名为counts_data。使用这个键名在字典中循环创建labelsdata

labels: [{% for label in counts_data %} '{{ label }}', {% endfor %}], 呈现为labels: [ 'to_do_count', 'in_progress_count', 'done_count', ],

data: [{% for label, value in counts_data.items() %} {{ value }}, {% endfor %}], 呈现为data: [ 3, 6, 1, ],

【讨论】:

  • 嗨,Achuth,看起来不错,你能告诉我如何更改views.py吗?我被困在输出所需的格式中
  • 我仍然不知道如何输出 [value1, value2, value3] 之类的东西,据我所知,counts_data=...agregate(..., ..., . ..) 是一个类似于 value list (value1, value2, value3) 的列表,但是当我返回时它需要是一个 dict,所以我把它变成 context = {"counts_data", counts_data},它类似于 {counts_data1 : (value1, value2, value3), counts_data2:(value1, value, value3),...},所以我不知道如何输出像 [value1, value2,value3] 这样的数据
  • 我试图将它们放入一个查询集中,但是一个查询集只能获取或过滤一个状态,我有 3 个状态,所以我很困惑,如果你能解释一下就好了?干杯
  • 在您的观点中,当您调用 aggregate() 时,您将在 counts_data 中获得值,其格式为 {'to_do_count': 1, 'in_progress_count': 1, 'done_count': 1}(请不要介意这些值)。这被分配给以counts_data 为键的上下文,然后在 html 中使用它来访问字典。通过循环,您实际上是在访问字典中的键和值,以按照指定的格式创建数据。希望这可以帮助。 (为确保您可以使用浏览器开发工具检查代码并查看其呈现方式)
  • 关于查询集中有 3 个状态:请查看文档docs.djangoproject.com/en/3.2/topics/db/aggregation/… 中本节的最后一个示例,您可以看到返回了一个字典。因此,在提供的代码中,您应该获得类似 {'to_do_count': 1, 'in_progress_count': 1, 'done_count': 1} 而不是 {counts_data1: (value1, value2, value3), counts_data2:(value1, value, value3),...} 的返回值
【解决方案2】:
<script>
 
$(document).ready(function() {
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
    labels: [1,2,3],
    
    datasets: [{
        label: '# of Votes',

        data:counts_data,

        success: function (data){
        $('#todocount').html(counts_data.to_do_count);
        $('#progress_count').html(counts_data.in_progress_count);

        $('#progress_done').html(counts_data.done_count);

    }
        
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)'
        ],
        borderColor: [
            'rgba(255, 99, 132, 1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)'
        ],
        borderWidth: 1
    }]
},
options: {
    responsive:false
    
}
});
});
</script>

【讨论】:

  • 嗨,Rahul,感谢您的帮助,我尝试了您的方法,但不起作用,您还有其他想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多