python - 如何在 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 %}
预期结果
如何向 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'):
请帮我
解决方案
推荐阅读
- arrays - 根据 mule Dataweave 中另一个列表中的值有效替换列表中的值
- excel - Having trouble getting Excel VBA code to execute consistently. First time using a collection
- pandas - How to plot two columns of a specific index range?
- amazon-web-services - Unable to tag EBS Volumes using UserData bash script
- python - Cant figure out why 'TypeError: function takes exactly 1 argument (2 given)' error is occurring?
- laravel - 如何在数据透视表上插入多个值?
- python - 检索字典中的键值
- python - 有没有办法在 Python/Jupyter 中创建类似案例的 IF 语句来使用 Tweepy 监视推文中的子字符串?
- javascript - Are there any options for inverting a bezier curve? (cytoscape.js)
- c# - changing a group of textbox controls to ReadOnly = false