#javascript #python #json #django #chart.js
#javascript #python #json #django #chart.js
Вопрос:
Я создаю веб-сайт информационной панели для некоторых имеющихся у меня датчиков качества воды, которые отправляют информацию в виде API в формате JSON. План состоит в том, чтобы создавать диаграммы в реальном времени с использованием этих данных с помощью chart.js и Джанго. Прямо сейчас я превращаю файл JSON в словари следующим образом:
JSON file:
{
"11:00:00 AM": {
"Temperatura": 30,
"pH": 7.1,
"Conductividad": 759,
"Cloro Residual": 1.1,
"Turbidez": 0,
"Color": "<5",
"pH de la Det de color": 7.12,
"Solidos totales": 512,
"S�lidos disueltos": 494,
"S�lidos suspendidos totales": 0,
"Dureza total como CaCO3": 227.24,
"Alcalinidad como CaCO3": 227.7,
"Cloruros": 64.02,
"Fluoruros": 0.91,
"Nitrogeno Amoniacal": 0,
"Nitrogeno de nitritos": 0,
"Nitrogeno de nitratos": 4.47,
"Sulfatos": 37.27,
"Sustancias activas al azul de metileno": 0,
"Fenoles": 0,
"Coliformes totales": 0,
"Aluminio": 0,
"Arsenico": 0.015,
"Bario": 0.1784,
"Calcio": 79.7,
"Cadmio": 0,
"Cromo": 0.0085,
"Cobre": 0,
"Fierro": 0.0327,
"Potasio": 12.18,
"Magnesio": 13.37,
"Manganeso": 0,
"Sodio": 55.75,
"Plomo": 0,
"Zinc": 0,
"Mercurio": 0
},
Затем я превращаю их в словари со всеми значениями следующим образом:
['11:00:00 AM', '11:10:05 AM', '11:20:10 AM', '11:30:14 AM', '11:40:19 AM', '11:50:24 AM', '12:00:29 PM', '12:10:34 PM', '12:20:38 PM', '12:30:43 PM', '12:40:48 PM', '12:50:53 PM', '01:00:58 PM', '01:11:03 PM', '01:21:07 PM', '01:31:07 PM']
[[30, 30, 28, 29, 19, 0, 0, 29, 31, 33, 27, 29, 27, 29, 30, 30], [7.1, 7.6, 7.5, 7.4, 7.5, 5, 8.5, 7.7, 7.2, 7.4, 7.2, 7.4, 7.3, 7.7, 7.7, 7.7], [759, 899, 869, 898, 833, '0', '', 841, 862, 826, 861, 896, 857, 836, 864, 864], [1.1, 0.7, 1, 0.3, 1.1, '0', 1.5, 1, 0.6, 1, 0.6, 0.3, 0.6, 1, 1, 1], [0, 0, 0, 0, 0, '0', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0], ['<5', '<5', '<5', '<5', '<5', '0', 20, '<5', '<5', '<5', '<5', '<5', '<5', '<5', '<5', '<5'], [7.12, 7.47, 7.4, 7.38, 7.42, '0', '', 7.58, 7.74, 7.53, 7.7, 7.45, 7.52, 7.55, 7.58, 7.58], [512, 598, 584, 599, 564, '0', '', 579, 576, 558, 586, 596, 593, 583, 569, 569], [494, 586, 562, 568, 530, '0', 1000, 538, 566, 550, 576, 564, 530, 558, 532, 532], [0, 0, 0, 0, 0, '0', '', 0, 0, 0, 0, 0, 0, 0, 0, 0], [227.24, 319.47, 296, 301.54, 263.56, '0', 500, 278.62, 292, 261.31, 298, 295.51, 300, 294.54, 279.54, 279.54], [227.7, 229.2, 222.1, 246.8, 213.4, '0', '', 232.6, 227.7, 224.8, 225.6, 44.2, 226.7, 225.4, 225.6, 225.6], [64.02, 112.16, 107, 111.17, 102.07, '0', 250, 93.69, 99.12, 91.32, 104.05, 106.7, 101.58, 96.16, 101.58, 101.58], [0.91, 0.9, 0.98, 0.94, 0.96, '0', 1.5, 1.07, 0.97, 1, 0.91, 0.94, 0.83, 0.88, 0.92, 0.92], [0, 0, 0, 0, 0, '0', 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0], [4.47, 4.21, 4.49, 4.51, 4.76, '0', 10, 4.01, 3.91, 3.96, 3.96, 4.67, 4.17, 3.94, 4.59, 4.59], [37.27, 43.75, 43.91, 43.33, 41.2, '0', 400, 43.39, 43.67, 42.1, 39.94, 46.48, 44.58, 42.52, 45.06, 45.06], [0, 0, 0, 0, 0, '0', 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.001, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0.015, 0.0128, 0.0121, 0.0137, 0.0147, '0', 0.05, 0.0147, 0.014, 0.0136, 0.0134, 0.0135, 0.0139, 0.0145, 0.0152, 0.0152], [0.1784, 0.192, 0.1893, 0.1783, 0.2004, '0', 0.7, 0.1913, 0.1741, 0.1762, 0.1716, 0.1763, 0.1749, 0.1906, 0.2021, 0.2021], [79.7, 102, 80.42, 93.63, 97.76, '0', '', 108.9, 84.7, 83.81, 82.5, 91.71, 86.72, 105.9, 103, 103], [0, 0, 0, 0, 0, '0', 0.005, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0.0085, 0.0043, 0.0049, 0.0077, 0.0088, '0', 0.05, 0.0073, 0.0065, 0.0073, 0.0063, 0.0078, 0.0066, 0.0071, 0.0097, 0.0097], [0, 0.0851, 0, 0.0075, 0, '0', 2, 0, 0.0623, 0.0071, 0.0102, 0.0112, 0.12, 0, 0, 0], [0.0327, 0, 0, 0, 0.0364, '0', 0.3, 0, 0, 0, 0, 0, 0, 0, 0.043, 0.043], [12.18, 11.9, 10.32, 11.51, 13.19, '0', '', 12.43, 10.58, 11.59, 10.28, 11.34, 10.86, 12.23, 13.27, 13.27], [13.37, 18.03, 15.31, 16.42, 17.23, '0', '', 15.85, 17.71, 14.72, 14.35, 16.03, 14.98, 15.6, 17.13, 17.13], [0, 0, 0, 0, 0, '0', 0.15, 0, 0, 0, 0, 0, 0, 0, 0, 0], [55.75, 56.45, 48.75, 54.63, 58.86, '0', 200, 52.8, 48.68, 53.42, 47.29, 53.85, 49.52, 52.47, 59.05, 59.05], [0, 0, 0, 0, 0, '0', 0.025, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0.0561, 0, 0, 0, '0', 5, 0, 0, 0.0394, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.001, 0, 0, 0, 0, 0, 0, 0.001, 0, 0]]
На моей странице просмотров я отправляю всю эту информацию в HTML, где chart.js создает диаграммы, используя эти данные.
from django.http import JsonResponse
from django.shortcuts import render
from django.views.generic import View
import json
from rest_framework.views import APIView
from rest_framework.response import Response
class HomeView(View):
def get(self, request, *args, **kwargs):
return render(request, 'charts.html', {})
def get_data(request, *args, **kwargs):
return JsonResponse(data)
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
with open("file.json") as f:
data = json.load(f)
labels_list = list(data)
a = list(data.values())[0]
filename = 'param_'
counter1 = 1
counter2 = 2
parameters = {}
for x in range(len(a.values())):
counter1 = str(counter1)
full_name = (filename counter1)
counter1 = counter2
counter2 = 1
full_values = []
for i in data:
v = labels_list.index(i)
aaa = list(data.values())[v]
val = list(aaa.values())[x]
full_values.append(val)
parameters[full_name] = full_values
labels = list(data)
name_param = list(a)
data = {
"labels": labels,
"values": list(parameters.values()),
"name_param": name_param,
}
return Response(data)
Моя проблема заключается в создании диаграмм, прямо сейчас мне приходится вручную создавать холст, присваивать им их идентификатор, создавать для них новый контекст и соответствующие им данные.
{% extends 'base.html' %}
<script>
{% block jquery %}
var endpoint = '/api/chart/data/'
var labels = []
var values = []
var name_param = []
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
labels = data.labels
values = data.values
name_param = data.name_param
console.log(data)
setChart()
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
function setChart(){
var ctx = document.getElementById('myChart');
var ctx2 = document.getElementById('myChart2');
var ctx3 = document.getElementById('myChart3');
var ctx4 = document.getElementById('myChart4');
var ctx5 = document.getElementById('myChart5');
var ctx6 = document.getElementById('myChart6');
var myChart = new Chart(ctx6, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[5],
data: values[5],
fill: false
}]
}
})
var myChart = new Chart(ctx5, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[4],
data: values[4],
fill: false
}]
}
})
var myChart = new Chart(ctx4, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[3],
data: values[3],
fill: false
}]
}
})
var myChart = new Chart(ctx3, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[2],
data: values[2],
fill: false
}]
}
})
var myChart = new Chart(ctx2, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[1],
data: values[1],
fill: false
}]
}
})
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: name_param[0],
data: values[0],
fill: false
}]
}
})
}
{% endblock %}
</script>
{% block content %}
<div class='row'>
<div class='col-sm-12' url-endpoint='{% url "api-data" %}'>
<h1>Hello World</h1>
<div class="col-sm-4">
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<div class="col-sm-4">
<canvas id="myChart2" width="400" height="400"></canvas>
</div>
<div class="col-sm-4">
<canvas id="myChart3" width="400" height="400"></canvas>
</div>
<div class="col-sm-4">
<canvas id="myChart4" width="400" height="400"></canvas>
</div>
<div class="col-sm-4">
<canvas id="myChart5" width="400" height="400"></canvas>
</div>
<div class="col-sm-4">
<canvas id="myChart6" width="400" height="400"></canvas>
</div>
</div>
</div>
{% endblock content %}
Мой вопрос в том, есть ли способ, возможно, иметь цикл for, который создает диаграмму для каждого параметра. Или как вы предложите создать несколько диаграмм?
Комментарии:
1. Привет, похоже, вы не дали никакого ответа на приведенный ниже ответ. Не могли бы вы сообщить мне, помогло ли это вам?
Ответ №1:
При просмотре ваших данных я думаю, что вы могли бы начать с улучшения структуры ваших данных. Причина этого в том, что данные — это единственное, что отличается для каждой диаграммы. Таким образом, настройка данных в соответствии с потребностями диаграммы — отличный способ упростить интерфейсу создание ваших диаграмм.
values
name_param
Оба списка и являются отдельными, но оба они связаны своими индексами. Это может быть улучшено путем создания name_param
/ value
групп в новом словаре. И присвоение имен свойствам, отражающим настройки Chart
экземпляра, будет еще лучше, например label
, и data
.
Попробуйте изменить свой список на следующую структуру.
{
labels: [], // Labels remains unchanged.
datasets: [ // New array with objects.
{
label: '', // previously known as name_param
data: '' // previously known as value
},
{
label: '',
data: ''
},
// ... etc.
]
}
Это позволяет легко перебирать каждую группу в dataset
свойстве и создавать новую диаграмму для каждого набора. Но сначала вам понадобятся некоторые вспомогательные функции, которые создают <div>
<canvas>
Chart
экземпляры , и .
Сначала <div>
и <canvas>
. Приведенная ниже функция создает как столбец начальной загрузки, так и элемент canvas, который будет размещен внутри DOM.
function createCanvasAndColumn() {
const column = document.createElement('div');
div.classList.add('col-sm-4');
const canvas = document.createElement('canvas');
canvas.width = 400;
canvas.height = 400;
column.append(canvas);
/**
* Return both the canvas and the column.
* The column is needed to append to the row.
* The canvas is needed to create a chart with.
*/
return { canvas, column };
}
Нам не нужен id
атрибут, поскольку у нас уже есть ссылка на элемент в canvas
константе. Холст будет добавлен к <div>
. Затем он возвращает объект со ссылкой на столбец (который нам нужно добавить в документ) и ссылкой на холст (который нам нужен для Chart
экземпляра).
Теперь для создания диаграмм. Я сохранил измененную структуру данных, предложенную в начале ответа, в виду того, как данные должны отображаться в вашем приложении, поэтому следующая функция использует эту структуру.
const chartsRow = document.getElementById('charts-row');
function createCharts({ labels, datasets }) {
/**
* Loop over each item in datasets and create a
* new chart for each item. Each chart is then returned
* resulting in an array of Chart instances.
*/
const charts = datasets.map((dataset) => {
const { canvas, column } = createCanvasAndColumn();
const chart = new Chart(canvas, {
type: 'line',
data: {
labels: labels,
datasets: [{
...dataset,
fill: false
}]
}
});
// Add column (and canvas) to the row.
chartsRow.append(column);
return chart;
});
/**
* Return the charts array. This is not mandatory,
* but it might come in handy if you'd need to access
* the Chart instances at some point.
*/
return charts;
}
Эта createCharts
функция ожидает объект с labels
dataset
ключом и . Он перебирает datasets
массив, чтобы создать элемент canvas для каждого набора. Затем этот элемент canvas будет использоваться для создания нового Chart
экземпляра. name
И value
каждого набора данных будет использоваться для установки данных этого Chart
экземпляра.
Возможно, вы заметили, что цикл завершен map
. Это будет перебирать каждый элемент в массиве и ожидает return
инструкции для каждого элемента. Это приведет к созданию нового массива на основе возвращаемых значений внутри цикла. charts
Константа фактически будет представлять собой массив Chart
экземпляров.
Теперь, когда эти функции установлены, все, что вам нужно сделать, это передать данные, полученные из вашего приложения Django, в createCharts
функцию для построения диаграмм.
Упростите выбор строки, добавив id
атрибут. Этот атрибут должен иметь уникальное значение. В createCharts
приведенном выше фрагменте элемент выбирается из документа для добавления диаграмм.
<div class='row' id="charts-row">
<div class='col-sm-12' url-endpoint='{% url "api-data" %}'>
<h1>Hello World</h1>
</div>
</div>
Отсюда вы вызываете свой запрос и передаете данные своей createCharts
функции, которая затем перебирает данные и создает диаграмму для каждого элемента.
const endpoint = '/api/chart/data/';
$.ajax({
method: "GET",
url: endpoint,
success: function(data) {
createCharts(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("error");
console.log(textStatus);
}
})