首页 > 解决方案 > 如何在 Python/Django 中过滤图表(Chart.js)中的日期?

问题描述

我需要你的帮助,这是我第一个使用 Python、Django 和 Chart.js 的项目。我必须为自动化测试创建月度报告。

做了什么:urls.py

path('launch/<str:pk>', views.launch_details, name='launch-detail'),
path('launch/<str:pk>/<str:feature_id>', views.launch_details, name='launch-detail'),
path('launch/<str:pk>/<str:launch_id>', views.launch_details, name='launch-detail'),
path('launch/<str:pk>/<str:feature_id>/<int:scenario_id>', views.launch_details, name='launch-detail'),
path('monthly_report/', views.monthly_report, name='monthly_report'),
path('last_monthly_report/', views.last_monthly_report, name='last_monthly_report')

模型.py

class MonthlyReport(models.Model):
    start_date = models.CharField(max_length=255, primary_key=True)
    launch_id = models.IntegerField()
    status = models.CharField(max_length=255)
    p1_passed = models.IntegerField()
    p1_total = models.IntegerField()
    p2_passed = models.IntegerField()
    p2_total = models.IntegerField()
    p3_passed = models.IntegerField()
    p3_total = models.IntegerField()

    class Meta:
        managed = False
        db_table = 'V_AT_MONTHLY_REPORT'

    def get_absolute_url(self):
        """Returns the url to access a detail record for this book."""
        return reverse('launch-detail', args=[str(self.launch_id)])

    def get_failed_p1_features_no(self):
        return self.p1_total - self.p1_passed

    def get_failed_p2_features_no(self):
        return self.p2_total - self.p2_passed

    def get_failed_p3_features_no(self):
        return self.p3_total - self.p3_passed

视图.py

def monthly_report(request, pk=-1, launch_id='#'):

    last_launches = Launch.objects.exclude(launch_id='-1').order_by('-launch_id')[:5]
    scenario_history_dict = {}
    for launch in last_launches:
        for feature in launch.features.all():
            for scenario in feature.scenarios.all():
                scenario_link = launch.get_absolute_url() + "/" + feature.feature_name + "/" + str(scenario.scenario_id)
                scenario_hist = ScenarioHist(scenario_link, scenario.status)
                if scenario.scenario_id in scenario_history_dict:
                    scenario_history_dict[scenario.scenario_id].append(scenario_hist)
                else:
                    scenario_history_dict.update({scenario.scenario_id: [scenario_hist]})

    launch = Launch.objects.get(pk=pk)
    context = {
        "launch": launch,
        "launch_id": launch_id,
        "dataMonthly_report": MonthlyReport.objects.all()
    }

    return render(request, 'monthly_report.html', context=context)


class ChartDataMonthlyReport(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None, from_date = '2020-09-18', to_date = '2020-09-30'):
        historical_launches_bymonth = []
        passed_no_p1 = []
        total_no_p1 = []
        passed_no_p2 = []
        total_no_p2 = []
        passed_no_p3 = []
        total_no_p3 = []

        total_no_p1 = list(map(add, passed_no_p1, total_no_p1))

        for launch in MonthlyReport.objects.order_by('start_date').exclude(launch_id='-1')\
 \
                .values('launch_id', 'p1_passed', 'p1_total',
                        'p2_passed', 'p2_total',
                        'p3_passed', 'p3_total'):
            historical_launches_bymonth.append(launch['launch_id'])
            passed_no_p1.append(launch['p1_passed'])
            total_no_p1.append(launch['p1_total'])
            passed_no_p2.append(launch['p2_passed'])
            total_no_p2.append(launch['p2_total'])
            passed_no_p3.append(launch['p3_passed'])
            total_no_p3.append(launch['p3_total'])

        failed_no_p1 = list(map(sub, total_no_p1, passed_no_p1))
        failed_no_p2 = list(map(sub, total_no_p2, passed_no_p2))
        failed_no_p3 = list(map(sub, total_no_p3, passed_no_p3))

        data_p1 = {
            'priority': 'P1',
            'passed_no': passed_no_p1,
            'total_no': total_no_p1,
            'failed_no': failed_no_p1,
        }

        data_p2 = {
            'priority': 'P2',
            'passed_no': passed_no_p2,
            'total_no': total_no_p2,
            'failed_no': failed_no_p2,
        }

        data_p3 = {
            'priority': 'P3',
            'passed_no': passed_no_p3,
            'total_no': total_no_p3,
            'failed_no': failed_no_p3,
        }

        all_data = {
            'data_p1': data_p1,
            'data_p2': data_p2,
            'data_p3': data_p3
        }

        snapshot_date = []
        at_required = []
        at_not_required = []
        at_unknown = []
        at_complited = []
        at_not_complited = []

        for launch in DailyCoverage.objects.order_by('snapshot_date') \
                .values('snapshot_date', 'at_required', 'at_not_required',
                        'at_unknown', 'at_complited',
                        'at_not_complited'):
            snapshot_date.append(launch['snapshot_date'])
            at_required.append(launch['at_required'])
            at_not_required.append(launch['at_not_required'])
            at_unknown.append(launch['at_unknown'])
            at_complited.append(launch['at_complited'])
            at_not_complited.append(launch['at_not_complited'])

        coverage_data = {
            'snapshot_date': snapshot_date,
            'at_required': at_required,
            'at_not_required': at_not_required,
            'at_unknown': at_unknown,
            'at_complited': at_complited,
            'at_not_complited': at_not_complited
        }
        data = {
           'historical_launches_bymonth_arr': historical_launches_bymonth,
           'all_data': [data_p1,data_p2,data_p3],
            'coverage_data': coverage_data
        }


        return Response(data)


每月报告.html

{% extends "base_generic.html" %}

{% block jquery %}
var endpoint = '/report/api/chart/monthlyData/'
var all_data=[]
var historicalLaunchesByMonthArr = []
var coverage_data=[]

$.ajax({
  method: "GET",
  url: endpoint,
  success: function(data) {
    all_data=data.all_data
    historicalLaunchesByMonthArr = data.historical_launches_bymonth_arr
    coverage_data=data.coverage_data
    setPriorityCharts()
  },
  error: function(error_data) {
    console.log('error')
    console.log(error_data)
  }
})

Chart.Chart.pluginService.register({
    beforeDraw: function(chart) {
        if (chart.config.type == "doughnut")  {
            if (chart.config.centerText.display !== null &&
                typeof chart.config.centerText.display !== 'undefined' &&
                chart.config.centerText.display) {
                drawTotals(chart);
            }
        }
    },
});

function drawTotals(chart) {

    var width = chart.chart.width,
    height = chart.chart.height,
    ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 114).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = chart.config.centerText.text,
    textX = Math.round((width - ctx.measureText(text).width) / 2),
    textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
}

function setPriorityCharts() {

    for (var chart in all_data) {

        var ctx = document.getElementById('historical_data_' + all_data[chart]["priority"]).getContext('2d');
        var myChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels: historicalLaunchesByMonthArr,
            datasets: [{
                data: all_data[chart]['total_no'],
                label: "Total",
                borderColor: "#223322",
                fill: false
              }, {
                data: all_data[chart]['passed_no'],
                label: "Passed",
                borderColor: "#00af00",
                fill: false
              }, {
                data: all_data[chart]['failed_no'],
                label: "Failed",
                borderColor: "#F7464A",
                fill: false
              }
            ]
          },
          options: {
            title: {
              display: true,
              text: 'Number of scenarios per build ' + all_data[chart]["priority"]
            },
            scales: {
                yAxes: [{
                    display: true,
                    ticks: {
                        suggestedMin: 0,    // minimum will be 0, unless there is a lower value.
                        // OR //
                        beginAtZero: true   // minimum value will be 0.
                    }
                }]
            }
          }
        });
    }
        var ctx = document.getElementById('daily_coverage_data').getContext('2d');
        var myChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels: coverage_data['snapshot_date'],
            datasets: [{
                data: coverage_data['at_required'],
                label: "Total",
                borderColor: "#223322",
                fill: false
              }, {
                data: coverage_data['at_complited'],
                label: "Implemented",
                borderColor: "#00af00",
                fill: false
              }, {
                data: coverage_data['at_not_complited'],
                label: "Not implemented",
                borderColor: "#F7464A",
                fill: false
              }
            ]
          },
          options: {
            title: {
              display: true,
              text: 'Daily coverage'
            },
            scales: {
                yAxes: [{
                    display: true,
                    ticks: {
                        suggestedMin: 0,    // minimum will be 0, unless there is a lower value.
                        // OR //
                        beginAtZero: true   // minimum value will be 0.
                    }
                }]
            }
          }
        });

}


{% endblock %}

{% block content %}
<h2>Last launches</h2>
<div style="margin-left: auto">
<h4>Select date: </h4>

    From :<input type="date" name="fromdate"/>
    To :<input type="date" name="todate"/>
</div>
<br>
<input type="submit" value="Search"/>

<div class="row">
    <div class="col-sm-6">
        <canvas id="historical_data_P1" class="chart"></canvas>
    </div>
    <div class="col-sm-6">
        <canvas id="historical_data_P2" class="chart"></canvas>
    </div>
    <div class="col-sm-6">
        <canvas id="historical_data_P3" class="chart"></canvas>
    </div>
    <div class="col-sm-6">
        <canvas id="daily_coverage_data" class="chart"></canvas>
    </div>
</div>

<h2>Tests history</h2>
<!--{{dataMonthly_report}}-->
<table class="table table-sm">
    <thead>
        <tr>
            <th scope="col">Start date</th>
            <th scope="col">Build No.</th>
            <th scope="col">Status</th>
            <th scope="col">P1 passed</th>
            <th scope="col">P1 failed</th>
            <th scope="col">P2 passed</th>
            <th scope="col">P2 failed</th>
            <th scope="col">P3 passed</th>
            <th scope="col">P3 failed</th>
        </tr>
    </thead>
    <tbody>
    {% for launch in dataMonthly_report %}
        <tr scope="row">
            <td>{{ launch.start_date }}</td>
            <td><a href="{{ launch.get_absolute_url }}">{{ launch.launch_id }}</a></td>
            <td class="{% if launch.status == 'Passed' %}table-success{%elif launch.status == 'Unstable' %}table-warning{% else %}table-danger{% endif %}">{{ launch.status }}</td>
            <td>{{ launch.p1_passed }} ({{ launch.p1_total}})</td>
            <td>{{ launch.get_failed_p1_features_no }}</td>
            <td>{{ launch.p2_passed }} ({{ launch.p2_total}})</td>
            <td>{{ launch.get_failed_p2_features_no }}</td>
            <td>{{ launch.p3_passed }} ({{ launch.p3_total}})</td>
            <td>{{ launch.get_failed_p3_features_no }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
{% endblock %}

预期结果

1

如何向 chart.js 提供值:“fromdate”、“todate”?在views.py中我接下来应该做什么?我只按手动添加的日期过滤:

class ChartDataMonthlyReport(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None, from_date = '2020-09-18', to_date = '2020-09-30'):

请帮我

标签: pythondjangochart.js

解决方案


推荐阅读