Как я могу добавить гистограмму в мою базу данных Django? - PullRequest
1 голос
/ 08 января 2020

Уважаемые участники сообщества,

Я очень надеюсь, что вы поможете мне добавить гистограмму в мой проект Django. 1. У меня есть база данных с около 1000 предметов. 2. Мне нужно иметь возможность визуализировать 3-месячные продажи для каждого товара, когда это необходимо. Не уверен, что это правильный подход.

вот мои модели.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 -->

Я должен создать кнопку запроса для графиков, а затем должен быть создан график с правильными параметрами.

Посмотрели на этот вопрос: Отображение нескольких гистограмм в django

Также искали через это решение https://code.djangoproject.com/wiki/Charts

И посмотрел на эту статью https://simpleisbetterthancomplex.com/tutorial/2018/04/03/how-to-integrate-highcharts-js-with-django.html

Последняя статья была самой ясной, и вы можете видеть, что я только что скопировал и вставил решение оттуда с небольшими изменениями , Вот сценарий, который я поместил в свою базу. html file:

<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 %}

Это мой первый вопрос в этом сообществе, так что если что-то не понятно, пожалуйста, помогите мне исправить это правильно.

в ожидании любых полезных ответов !!!

Ответы [ 2 ]

1 голос
/ 10 января 2020

views.py У вас есть ошибка в аннотации (3м3, здесь она не может начинаться с 3. У вас также есть диаграммы с одинаковыми именами функций и имен переменных). Python может быть достаточно умен, чтобы понять это, но попытайтесь избегайте этого. Я также против явного указания имен переменных saleslm и sales2m.

def charts(request):
    return render(request, 'charts.html')


def charts_ajax(request):
    charts_data = Itemslist.objects \
        .values('saleslm') \
        .annotate(lm=Count('saleslm')) \
        .annotate(m2=Count('sales2m')) \
        .annotate(m3=Count('sales3m')) \
        .order_by('saleslm')
    return JsonResponse({'charts': list(charts_data)})

url.py

path('charts/', views.charts, name='charts_home'),
path('charts_ajax/', views.charts_ajax, name='render_charts_ajax')

html У вас есть несколько проблем в html файл.

</html>
{% endif %}
<div></div>
{% endblock js %}

У вас есть div после окончания html. У вас не должно быть ничего после окончания html. Несколько других организационных проблем здесь. Обычно у меня есть содержимое блока, а затем блок js пока у вас все внутри блока js. Я бы почистил их. Теперь, когда вы также добавили таблицы данных. Вы можете добавить кнопки, как указано здесь. https://datatables.net/extensions/buttons/examples/initialisation/custom.html но на вашем месте я бы попытался заставьте его работать с простой таблицей и перейдите к таблицам.

<html>
<head>
<meta charset="utf-8">
<title>Django Highcharts Example</title>
</head>
<body>
<div id="container">
</div>
<button id="render_chart" type="button">Render Chart</button>

<script
  src="https://code.jquery.com/jquery-3.4.1.min.js"
  integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
  crossorigin="anonymous"></script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script>
$(document).ready(function(){
   $('#render_chart').on('click', function(e){
       $.ajax({
           url: "{% url 'render_charts_ajax'%}",
           type: "GET",
           dataType: "json",
           success: function (data) {
               console.log(data.charts[0].saleslm)
               Highcharts.chart('container',{
                   chart:{
                       type:'bar'
                   },
                   title:{
                     text:"Sales Last Month"
                   },
                   series:[{
                       name:"Sales LM",
                       data:[parseInt(data.charts[0].saleslm)]
                   }]
               })
           }
       })
   })
});
</script>

</body>
</html>

Ваш json может потребовать некоторой обработки, прежде чем график выйдет правильно.

0 голосов
/ 15 января 2020

Сообщество хороших новостей.

Мне предложили очень хорошее решение, и теперь мой вопрос полностью рассортирован.

По крайней мере, для моих нужд это идеальное решение.

вместо высоких таблиц Мне предложили использовать d3 js .org, что совершенно нормально для меня.

Логика c, стоящая за кодом, заключается в том, что вы запрашиваете данные из отображаемых значений, надеюсь, будет понятно, когда вы будете go просматривать код с комментариями.

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

, чтобы помочь сообществу, задавайте вопросы и, пожалуйста, добавляйте / исправляйте, если есть лучший способ.

Большое спасибо за помощь и внимание !!!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...