python - 如何将条形图添加到基于 Django 的数据库?

标签 python django graph charts highcharts

亲爱的社区成员,

我真的希望你能帮助我将条形图添加到我的 Django 项目中。 1. 我有一个包含大约 1000 个项目的数据库。 2. 我需要能够在需要时直观地看到每件商品 3 个月的销售额。 不确定什么是正确的方法。

这是我的 models.py:

从 django.db 导入模型 从数学导入* 从十进制导入 *

class Itemslist(models.Model):
    item_n = models.CharField(max_length=200)
    sales_this_month = models.DecimalField(blank=True, null=True, max_digits=19, 
    decimal_places=0)
    saleslm = models.DecimalField(blank=True, null=True, max_digits=19, decimal_places=0)
    sales2m = models.DecimalField(blank=True, null=True, max_digits=19, decimal_places=0)
    sales3m = models.DecimalField(blank=True, null=True, max_digits=19, decimal_places=0)


    def __str__(self):
        return self.item_n

这是我的views.py 文件,作为我使用最后提供的解决方案创建的实验:

def charts(request):
    charts = Itemslist.objects \
        .values('saleslm') \
        .annotate(lm=Count('saleslm')) \
        .annotate(m2=Count('sales2m')) \
        .annotate(3m3=Count('sales3m')) \
        .order_by('saleslm')
    return render(request, 'charts.html', {'charts': charts})
正如您所看到的,这不是我需要的解决方案,我只是想至少想出一些东西,甚至已经向我显示了具有相同值的图表。 这是我的 hmtl 代码:

{% extends 'base.html' %}
{% block js %}
{% if user.is_authenticated %}
{% load loads_extra %}
{% load static %}

<br>
<p>Logged in user: {{ user.username }}</p>
<br>


<html>
<head>
<meta charset="utf-8">
<title>Django Highcharts Example</title>
</head>
<body>
<div id="container"></div>
{
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script>
  Highcharts.chart('container', {
      chart: {
          type: 'column'
      },
      title: {
          text: 'Sales previous 3 months'
      },
      xAxis: {
          categories: ['sales']
      },
      series: [{
          name: '3mBack',
          data: [ {% for entry in charts %}{{ entry.m3 }}{% endfor %} ]
      }, {
          name: '2mBack',
          data: [ {% for entry in charts %}{{ entry.m2 }}{% endfor %} ]
      }, {
          name: 'Lmonth',
          data: [ {% for entry in charts %}{{ entry.lm }}{% endfor %} ]
      }, ]

  });
</script>

</body>
</html>

{% endif %}
{% endblock %}

<!-- charting tutorial to follow :  https://simpleisbetterthancomplex.com/tutorial/2018/04/03/how-to-integrate-highcharts-js-with-django.html -->

我必须为图表创建一个请求按钮,然后必须使用正确的参数生成图表。

看过这个问题: Displaying multiple bar graph in django

也搜索过这个解决方案 https://code.djangoproject.com/wiki/Charts

并查看了这篇文章 https://simpleisbetterthancomplex.com/tutorial/2018/04/03/how-to-integrate-highcharts-js-with-django.html

上一篇文章是最清晰的,您可以看到,我刚刚从那里复制粘贴了解决方案,并进行了一些小更改。 这是我放置在 base.html 文件中的脚本:

<script src="https://code.highcharts.com/highcharts.src.js"></script>

这就是我最终显示的图表:

Highchart

但在我的情况下仍然找不到如何处理它。

据我所知,所有这些解决方案都展示了如何对一个数组进行图表绘制,或者对数组求和或自行生成数组。但我希望能够选择何时显示图表以及针对哪个项目。

按钮放置在这个 html 文件上:

{% extends 'base.html' %}
{% block js %}
{% if user.is_authenticated %}
{% load loads_extra %}
{% load static %}

<br>
<p>Logged in user: {{ user.username }}</p>
<br>


    <body>
            <table id="example" class="table table-striped table-bordered dt-responsive nowrap" style="width:100%">
            <thead>
            <tr>
              <th>SUP:</th>
              <th>Item N.:</th>
              <th>SKU</th>
              <th>Description</th>
              <th>3mBack</th>
              <th>2mBack</th>
              <th>Lmonth</th>
              <th>CMonth</th>
              <th>Nmonth</th>
              <th>N2Month</th>
              <th>N3month</th>
              <th></th>

            </tr>
            </thead>
            <tbody>
                        {% for records in sorted %}
                <tr>
                <td>{{ records.sup }}</td>
                <td>{{ records.item_n }}</td>
                <td>{{ records.sku }}</td>
                <td>{{ records.description }}</td>
                <td>{{ records.sales3m }}</td>
                <td>{{ records.sales2m }}</td>
                <td>{{ records.saleslm }}</td>
                <td>{{ records.sales_this_month }}</td>
                <td>{{ records.m1predicted }}</td>
                <td>{{ records.m2predicted }}</td>
                <td>{{ records.m3predicted }}</td>

                <td>
                  <a href="{% url 'edit' records.id %}" class="btn btn-secondary">Edit</a>
                </td>

                            </tr>
                        {% endfor %}

            </tbody>
        </table>

        <script>
        $(document).ready(function() {
            var table = $('#example').DataTable( {
            fixedColumns: true,
                lengthChange: true,
                buttons: [ 'copy', 'excel', 'csv', 'pdf', 'colvis' ]
            } );

            table.buttons().container()
                .appendTo( '#example_wrapper .col-md-6:eq(0)' );
        } );
         </script>
    </body>
</html>
{% endif %}
<div></div>
{% endblock js %}

这是我在这个社区的第一个问题,所以如果有不清楚的地方,请帮助我以正确的方式纠正。

等待任何有用的答案!!!

最佳答案

好消息社区。

我得到了一个非常好的解决方案,现在我的问题已经完全解决了。

至少对于我的需求来说,这是一个完美的解决方案。

我被提议使用 d3js.org,而不是 highcharts,这对我来说绝对没问题。

代码背后的逻辑是,您从显示的值中请求数据,希望当您使用注释浏览代码时,它会很清楚。

因为它是一个 django 项目,所以这是我的 html 文件的标题:

{% extends 'base.html' %}
{% block js %}
{% if user.is_authenticated %}
{% load loads_extra %}
{% load static %}

<br>
<p>Logged in user: {{ user.username }}</p>
<br>

这是我的 html 代码的一部分,用于显示表/值:

<table id="example" class="table table-striped table-bordered dt-responsive nowrap" style="width:100%">
            <thead>
            <tr>
              <th>SUP:</th>
              <th>Item N.:</th>
              <th>SKU</th>
              <th>Description</th>
              <th>6mBack</th>
              <th>5mBack</th>
              <th>4mBack</th>
              <th>3mBack</th>
              <th>2mBack</th>
              <th>Lmonth</th>
              <th>CMonth</th>
              <th>Nmonth</th>
              <th>N2Month</th>
              <th>N3month</th>
              <th>AVGrowth</th>
              <th></th>
              <!-- This is header for new button to draw the Bar Charts -->
              <th></th>

            </tr>
            </thead>
            <tbody>
              {% for records in sorted %}
                <tr>
                <td>{{ records.sup }}</td>
                <td>{{ records.item_n }}</td>
                <td>{{ records.sku }}</td>
                <td>{{ records.description }}</td>
                <td>{{ records.sales6m }}</td>
                <td>{{ records.sales5m }}</td>
                <td>{{ records.sales4m }}</td>
                <td>{{ records.sales3m }}</td>
                <td>{{ records.sales2m }}</td>
                <td>{{ records.saleslm }}</td>
                <td>{{ records.sales_this_month }}</td>
                <td>{{ records.m1predicted }}</td>
                <td>{{ records.m2predicted }}</td>
                <td>{{ records.m3predicted }}</td>
                <td>{{ records.avgrowths }}</td>

                <td>
                  <a href="{% url 'edit' records.id %}" class="btn btn-secondary">Edit</a>
                </td>
                <!-- Add new button for drawing Bar Charts -->
                <td>
                  <button class="btn btn-secondary" onclick="draw_chart(this)" data-toggle="modal" data-target="#myModal">Chart</button>
                </td>

            </tr>
          {% endfor %}

         </tbody>
        </table>

请阅读评论以了解什么是什么。

这是 html 的其余部分,即通过按下必须可视化的数组前面的按钮,在充值窗口上生成图表:

<!-- Modal which Bar Chart will be placed -->
        <div id="myModal" class="modal fade" role="dialog">
            <div class="modal-dialog" style="max-width: 900px !important">
            <!-- Modal content-->
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                    </div>
                    <div class="modal-body">
                        <!-- <svg> element which will contains the Bar Chart -->
                        <svg width="1000" height="500"></svg>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>
        <!-- Insert D3.js Library -->
        <script src="https://d3js.org/d3.v5.min.js"></script>
        <script>
        $(document).ready(function() {
            var table = $('#example').DataTable( {
            fixedColumns: true,
                lengthChange: true,
                buttons: [ 'copy', 'excel', 'csv', 'pdf', 'colvis' ]
            } );

            table.buttons().container()
                .appendTo( '#example_wrapper .col-md-6:eq(0)' );
        } );
        // Main functions for Drawing Bar chart using D3.js
        function draw_chart(item){
            // `item` is the current clicked button element
            // `row_ele` is the parent <tr> element of the current clicked button element
            row_ele = item.closest('tr');
            // Get the value from the <td> element using nth-child()
            val_6mBack = row_ele.querySelector("td:nth-child(5)");
            val_5mBack = row_ele.querySelector("td:nth-child(6)");
            val_4mBack = row_ele.querySelector("td:nth-child(7)");
            val_3mBack = row_ele.querySelector("td:nth-child(8)");
            val_2mBack = row_ele.querySelector("td:nth-child(9)");
            val_Lmonth = row_ele.querySelector("td:nth-child(10)");
            val_CMonth = row_ele.querySelector("td:nth-child(11)");
            val_Nmonth = row_ele.querySelector("td:nth-child(12)");
            val_N2Month = row_ele.querySelector("td:nth-child(13)");
            val_N3month = row_ele.querySelector("td:nth-child(14)");

            // `data` is variable which store the data for Bar Charts
            data = []
            // Pushing data as key/value type objects into the `data` variable
            data.push({'label':'6mBack', 'value': val_6mBack.innerHTML})
            data.push({'label':'5mBack', 'value': val_5mBack.innerHTML})
            data.push({'label':'4mBack', 'value': val_4mBack.innerHTML})
            data.push({'label':'3mBack', 'value': val_3mBack.innerHTML})
            data.push({'label':'2mBack', 'value': val_2mBack.innerHTML})
            data.push({'label':'Lmonth', 'value': val_Lmonth.innerHTML})
            data.push({'label':'CMonth', 'value': val_CMonth.innerHTML})
            data.push({'label':'Nmonth', 'value': val_Nmonth.innerHTML})
            data.push({'label':'N2Month', 'value': val_N2Month.innerHTML})
            data.push({'label':'N3month', 'value': val_N3month.innerHTML})


            // Set <svg> element's width and height
            var svg = d3.select("svg"),
                        margin = 200,
                        width = svg.attr("width") - margin,
                        height = svg.attr("height") - margin
            // Remove the old contents of the <svg> element
            svg.selectAll('*').remove()
            // Initialize X-axis and Y-axis for Bar Chart
            var xScale = d3.scaleBand().range([0, width]).padding(0.4),
                yScale = d3.scaleLinear().range([height, 0]);

            // Set all group which is placed in the <svg>element
            // transform to (50,100) on <svg> area , margint in svg has been changed to 300 and instead 50/100, changed to 100/300, but then back.
            var g = svg.append("g")
                        .attr("transform", "translate(" + 50 + "," + 100 + ")");


            xScale.domain(data.map(function(d) { return d.label; }));
            // If all values of data will be zero, we will fix the range of the Y-axis
            if(d3.max(data, function(d) { return d.value; }) == 0){
                yScale.domain([0, 10]);
            }else{
                // If all is not zero, we will set Y-axis from 0 to maximum value.
                yScale.domain([0, d3.max(data, function(d) { return Number(d.value); })]);
            }

            // Set X- axis
            g.append("g")
             .attr("transform", "translate(0," + height + ")")
             .call(d3.axisBottom(xScale));
             // Set Y-axis using ticket
            g.append("g")
             .call(d3.axisLeft(yScale).tickFormat(function(d){
                 return d;
             }).ticks(10));

             console.log(data)
            // Draw Bar Chart using <rect> element by data which is stored in the `data` variable
            g.selectAll(".bar")
             .data(data)
             .enter().append("rect")
             .attr("class", "bar")
             .attr("x", function(d) { return xScale(d.label); })
             .attr("y", function(d) { return yScale(d.value); })
             .attr("width", xScale.bandwidth())
             .attr("height", function(d) { return height - yScale(d.value); })
             .style('fill','#899da6');
        }
        </script>
    </body>
{% endif %}
{% endblock js %}

最后我的 html 看起来是这样的:

enter image description here

这是一个图表,我通过按图表按钮获得:

enter image description here

为了帮助社区,请提出问题,如果有更好的方法,请添加/更正。

非常感谢您的帮助和关注!!!

关于python - 如何将条形图添加到基于 Django 的数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59648379/

相关文章:

python - 如何在 PySpark 1.6.1 中将第二个数据帧的列传递到 UDF 中

database - Django 部署 : Handling data in database

java - Apache POI 图表与日期

javascript - 如何检测 D3 中条形图上指针下方最近的矩形?

python - 将附加参数传递给 Python 管道 (pipetools)

python - Python中的CSV在Windows上添加了一个额外的回车符

python - 单独线程中 Python 中的按键回显不显示第一个击键

python - Django:在允许用户注册之前检查用户是否已登录?

django - Tastypie-获取正在编辑的对象的列表(PUT/PATCH)

azure - 用于获取带有员工 ID 的整个用户列表的图形 API