制作一个好的 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)