制作一个好的 Json 文件以在 highchart 中显示
make a good Json file to show in highchart
大家好,希望你们一切顺利,我想做一个图表来显示每个办公室的流程(比如每个办公室每天的交付排名),
models.py
class Evenement(models.Model):
EVENEMENT_CHOICES = (
("déposé","déposé"),
("reçu","reçu"),
("expédié","expédié"),
("affecté","affecté"),
("livré","livré"),
("echec de livraison","echec de livraison"),
)
mail_item_fid = models.ForeignKey(mail_item,on_delete=models.CASCADE, related_name='mail_item_fid_evenement')
from_office = models.ForeignKey(Office,on_delete=models.CASCADE, related_name='office_Evt_evenement')
date_Evt = models.DateTimeField()
status = models.CharField(max_length=50,choices=EVENEMENT_CHOICES)
agent_delivery_cd = models.ForeignKey(Delivery_Agent,on_delete=models.CASCADE,blank=True, null=True ,related_name='agent_evenement')
def __str__(self):
return '{}, {}, {}, {} '.format(self.mail_item_fid,self.from_office,self.date_Evt,self.status)
views.py
@login_required
def dataOfChart(request):
dataset = Evenement.objects.annotate(Day=TruncDay('date_Evt')).values('Day','from_office')\
.annotate(depot=Count('from_office',filter=Q(status='déposé')),
affecte=Count('from_office',filter=Q(status='affecté')),
livre=Count('from_office',filter=Q(status="livré")),
taux=Cast(F('livre'), FloatField())/Cast(F('affecte'), FloatField())).all().order_by('from_office','Day')
location_data = list(dataset)
date = Evenement.objects.annotate(Day=TruncDay('date_Evt'))\
.values_list('Day')\
.annotate(count=Count('id'))\
.values_list('Day')\
.order_by('Day')\
.filter(count__gt=1)
datetime_list = list(date)
return render(request, 'charts_event_list.html', {'location_data': location_data ,'datetime_list':json.dumps(datetime_list,sort_keys=True,indent=1,cls=DjangoJSONEncoder)} )
template.html
<body>
<div id="container"></div>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script>
Highcharts.chart('container', {
chart: {
type: 'line'
},
title: {
text: 'deliveries rate per offices '
},
xAxis: {
categories: {%for Day in datetime_list %}{{Day|safe}}{%endfor %}
},
series: [
{% for data in location_data %}
{
name: //here it should stock 'from_office' once,
data: //here it should update the 'taux',
},
{% endfor %}
]
});
</script>
</body>
我的json文件location_data如下所示,
[
{
"from_office": 1,
"Day": "2020-06-19T00:00:00Z",
"taux": 1.0
},
{
"from_office": 1,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 2,
"Day": "2020-06-19T00:00:00Z",
"taux": 0.0
},
{
"from_office": 2,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 3,
"Day": "2020-06-20T00:00:00Z",
"taux": 0.5
}
]
我想实现这样的目标,这样 highchart 就可以只读取一次名称并更新其数据 =>
series: [
{
name: 'office name 1 ',
data: [0,0.25,1],
},
{
name: 'office name 2 ',
data: [0,1,0.75],
},
]
在 views.py
中,您应该将数据分组以创建列表
series = [{"name": 'office name 1', "data": [0, 0.25, 1]}, ... ]
因为它需要的不仅仅是 for
-loop 并且在模板中执行它可能是个大问题 - 如果可能的话。
此外views
用于(重新)组织数据,模板仅用于显示。
当您获得此列表时,您可以发送或不发送 json.dumps()
。
如果您在没有 json.dumps()
的情况下发送到模板
render(request, 'charts_event_list.html', {'series': series, ... })
然后在模板中使用 for
-loop
series: [
{% for item in series %}
{
name: {% item.name %}
data: {% item.data %}
},
{% endfor %}
]
如果您使用 json.dumps()
发送(创建包含所有数据的单个字符串)
render(request, 'charts_event_list.html', {'series': json.dumps(series), ... })
然后直接放在模板里
series: {{ series }}
这里的示例代码将 taux
分组
import json
location_data = [
{
"from_office": 1,
"Day": "2020-06-19T00:00:00Z",
"taux": 1.0
},
{
"from_office": 1,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 2,
"Day": "2020-06-19T00:00:00Z",
"taux": 0.0
},
{
"from_office": 2,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 3,
"Day": "2020-06-20T00:00:00Z",
"taux": 0.5
}
]
series_dict = {}
for item in location_data:
office = item['from_office']
taux = item['taux']
if office not in series_dict:
series_dict[office] = {
'name': 'office name {}'.format(office),
'data': []
}
series_dict[office]['data'].append(taux)
series = list(series_dict.values())
print('\n--- series as dict ---\n')
print( series_dict )
print('\n--- series as list ---\n')
print( series )
print('\n--- series as text ---\n')
text = json.dumps(series)
print( text )
结果:
--- series as dict ---
{1: {'name': 'office name 1', 'data': [1.0, 1.0]}, 2: {'name': 'office name 2', 'data': [0.0, 1.0]}, 3: {'name': 'office name 3', 'data': [0.5]}}
--- series as list ---
[{'name': 'office name 1', 'data': [1.0, 1.0]}, {'name': 'office name 2', 'data': [0.0, 1.0]}, {'name': 'office name 3', 'data': [0.5]}]
--- series as text ---
[{"name": "office name 1", "data": [1.0, 1.0]}, {"name": "office name 2", "data": [0.0, 1.0]}, {"name": "office name 3", "data": [0.5]}]
编辑:
最终你可以使用pandas
来分组数据
import pandas as pd
# convert dict to DataFrame (table)
df = pd.DataFrame.from_dict(location_data)
# get only columns 'from_office', 'taux'
#df = df[ ['from_office', 'taux'] ]
# groups all data using values in column 'from_office'
groups = df.groupby('from_office')
# convert groups to list
series = [{
'name': 'office name {}'.format(office),
'data': values['taux'].to_list()
} for office, values in groups]
print('\n--- pandas ---\n')
print(series)
大家好,希望你们一切顺利,我想做一个图表来显示每个办公室的流程(比如每个办公室每天的交付排名),
models.py
class Evenement(models.Model):
EVENEMENT_CHOICES = (
("déposé","déposé"),
("reçu","reçu"),
("expédié","expédié"),
("affecté","affecté"),
("livré","livré"),
("echec de livraison","echec de livraison"),
)
mail_item_fid = models.ForeignKey(mail_item,on_delete=models.CASCADE, related_name='mail_item_fid_evenement')
from_office = models.ForeignKey(Office,on_delete=models.CASCADE, related_name='office_Evt_evenement')
date_Evt = models.DateTimeField()
status = models.CharField(max_length=50,choices=EVENEMENT_CHOICES)
agent_delivery_cd = models.ForeignKey(Delivery_Agent,on_delete=models.CASCADE,blank=True, null=True ,related_name='agent_evenement')
def __str__(self):
return '{}, {}, {}, {} '.format(self.mail_item_fid,self.from_office,self.date_Evt,self.status)
views.py
@login_required
def dataOfChart(request):
dataset = Evenement.objects.annotate(Day=TruncDay('date_Evt')).values('Day','from_office')\
.annotate(depot=Count('from_office',filter=Q(status='déposé')),
affecte=Count('from_office',filter=Q(status='affecté')),
livre=Count('from_office',filter=Q(status="livré")),
taux=Cast(F('livre'), FloatField())/Cast(F('affecte'), FloatField())).all().order_by('from_office','Day')
location_data = list(dataset)
date = Evenement.objects.annotate(Day=TruncDay('date_Evt'))\
.values_list('Day')\
.annotate(count=Count('id'))\
.values_list('Day')\
.order_by('Day')\
.filter(count__gt=1)
datetime_list = list(date)
return render(request, 'charts_event_list.html', {'location_data': location_data ,'datetime_list':json.dumps(datetime_list,sort_keys=True,indent=1,cls=DjangoJSONEncoder)} )
template.html
<body>
<div id="container"></div>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script>
Highcharts.chart('container', {
chart: {
type: 'line'
},
title: {
text: 'deliveries rate per offices '
},
xAxis: {
categories: {%for Day in datetime_list %}{{Day|safe}}{%endfor %}
},
series: [
{% for data in location_data %}
{
name: //here it should stock 'from_office' once,
data: //here it should update the 'taux',
},
{% endfor %}
]
});
</script>
</body>
我的json文件location_data如下所示,
[
{
"from_office": 1,
"Day": "2020-06-19T00:00:00Z",
"taux": 1.0
},
{
"from_office": 1,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 2,
"Day": "2020-06-19T00:00:00Z",
"taux": 0.0
},
{
"from_office": 2,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 3,
"Day": "2020-06-20T00:00:00Z",
"taux": 0.5
}
]
我想实现这样的目标,这样 highchart 就可以只读取一次名称并更新其数据 =>
series: [
{
name: 'office name 1 ',
data: [0,0.25,1],
},
{
name: 'office name 2 ',
data: [0,1,0.75],
},
]
在 views.py
中,您应该将数据分组以创建列表
series = [{"name": 'office name 1', "data": [0, 0.25, 1]}, ... ]
因为它需要的不仅仅是 for
-loop 并且在模板中执行它可能是个大问题 - 如果可能的话。
此外views
用于(重新)组织数据,模板仅用于显示。
当您获得此列表时,您可以发送或不发送 json.dumps()
。
如果您在没有 json.dumps()
render(request, 'charts_event_list.html', {'series': series, ... })
然后在模板中使用 for
-loop
series: [
{% for item in series %}
{
name: {% item.name %}
data: {% item.data %}
},
{% endfor %}
]
如果您使用 json.dumps()
发送(创建包含所有数据的单个字符串)
render(request, 'charts_event_list.html', {'series': json.dumps(series), ... })
然后直接放在模板里
series: {{ series }}
这里的示例代码将 taux
import json
location_data = [
{
"from_office": 1,
"Day": "2020-06-19T00:00:00Z",
"taux": 1.0
},
{
"from_office": 1,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 2,
"Day": "2020-06-19T00:00:00Z",
"taux": 0.0
},
{
"from_office": 2,
"Day": "2020-06-20T00:00:00Z",
"taux": 1.0
},
{
"from_office": 3,
"Day": "2020-06-20T00:00:00Z",
"taux": 0.5
}
]
series_dict = {}
for item in location_data:
office = item['from_office']
taux = item['taux']
if office not in series_dict:
series_dict[office] = {
'name': 'office name {}'.format(office),
'data': []
}
series_dict[office]['data'].append(taux)
series = list(series_dict.values())
print('\n--- series as dict ---\n')
print( series_dict )
print('\n--- series as list ---\n')
print( series )
print('\n--- series as text ---\n')
text = json.dumps(series)
print( text )
结果:
--- series as dict ---
{1: {'name': 'office name 1', 'data': [1.0, 1.0]}, 2: {'name': 'office name 2', 'data': [0.0, 1.0]}, 3: {'name': 'office name 3', 'data': [0.5]}}
--- series as list ---
[{'name': 'office name 1', 'data': [1.0, 1.0]}, {'name': 'office name 2', 'data': [0.0, 1.0]}, {'name': 'office name 3', 'data': [0.5]}]
--- series as text ---
[{"name": "office name 1", "data": [1.0, 1.0]}, {"name": "office name 2", "data": [0.0, 1.0]}, {"name": "office name 3", "data": [0.5]}]
编辑:
最终你可以使用pandas
来分组数据
import pandas as pd
# convert dict to DataFrame (table)
df = pd.DataFrame.from_dict(location_data)
# get only columns 'from_office', 'taux'
#df = df[ ['from_office', 'taux'] ]
# groups all data using values in column 'from_office'
groups = df.groupby('from_office')
# convert groups to list
series = [{
'name': 'office name {}'.format(office),
'data': values['taux'].to_list()
} for office, values in groups]
print('\n--- pandas ---\n')
print(series)