Я пытаюсь создать небольшое веб-приложение, извлекающее данные из базы данных MySQL с помощью фильтра даты ajax и применяющее даты, а также отображающую таблицу и диаграмму во внешнем интерфейсе. Я могу получить таблицу с помощью моего скрипта, не могу получить диаграмму, как внести изменения для получения диаграммы и стол тоже это файл main.py
from flask import Flask, render_template, request, jsonify, flash, redirect
from flask_mysqldb import MySQL, MySQLdb # pip install flask-mysqldb https://github.com/alexferl/flask-mysqldb
app = Flask(__name__)
app.secret_key = "caircocoders-ednalan"
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'xxxx'
app.config['MYSQL_DB'] = "battery_voltage"
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
mysql = MySQL(app)
@app.route('/')
def index():
cursor= mysql.connection.cursor()
cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cur.execute("SELECT * FROM voltage ORDER BY date desc")
orders = cur.fetchall()
return render_template('index.html', orders=orders)
@app.route("/range", methods=["POST", "GET"])
def range():
cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
if request.method == 'POST':
From = request.form['From']
to = request.form['to']
print(From)
print(to)
query = "SELECT * FROM voltage WHERE date BETWEEN '{}' AND '{}'".format(From, to)
cur.execute(query)
ordersrange = cur.fetchall()
return jsonify({'htmlresponse': render_template('response.html', ordersrange=ordersrange)})
if __name__ == "__main__":
app.run(debug=True,port = "2021")
index.html
<!doctype html>
<html>
<head>
<meta charset = "UTF-8">
<title>Python Flask Date Range Search with jQuery Ajax DatePicker MySQL Database</title>
<link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
<link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css"/>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
</style>
</head>
<body>
<br/>
<div class = "container">
<h2 align = "left">OPSPOD Battery Voltage</h2>
<br/>
<br/>
<div class = "col-md-2">
<input type = "text" name = "From" id = "From" class = "form-control" placeholder = "From Date"/>
</div>
<div class = "col-md-2">
<input type = "text" name = "to" id = "to" class = "form-control" placeholder = "To Date"/>
</div>
<div class = "col-md-8">
<input type = "button" name = "range" id = "range" value = "Range" class = "btn btn-success"/>
</div>
<div class = "clearfix"></div>
<br/>
<div id = "purchase_order">
<table class = "table table-bordered" style = "width:40%" align = "left" >
<tr>
<th width = "5%">Date</th>
<th width = "4%">Time</th>
<th width = "4%">voltage</th>
<th width = "4%">ignition</th>
</tr>
{% for row in orders %}
<tr>
<td>{{row.date}}</td>
<td>{{row.time}}</td>
<td>{{row.voltage}}</td>
<td>{{row.ignition}}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<!-- Script -->
<script>
$(document).ready(function(){
$.datepicker.setDefaults({
dateFormat: 'dd-mm-yy'
});
$(function(){
$("#From").datepicker();
$("#to").datepicker();
});
$('#range').click(function(){
var From = $('#From').val();
var to = $('#to').val();
if (From != '' && to != '')
{
$.ajax({
url:"/range",
method:"POST",
data:{From:From, to:to},
success:function(data)
{
$('#purchase_order').html(data);
$('#purchase_order').append(data.htmlresponse);
}
});
}
else
{
alert("Please Select the Date");
}
});
});
</script>
</body>
</html>
ответ.html
<table class = "table table-bordered" style = "width:40%" align = "left" >
<tr>
<th width = "5%">Date</th>
<th width = "4%">Time</th>
<th width = "4%">voltage</th>
<th width = "4%">ignition</th>
</tr>
{% for row in ordersrange %}
<tr>
<td>{{row.date}}</td>
<td>{{row.time}}</td>
<td>{{row.voltage}}</td>
<td>{{row.ignition}}</td>
</tr>
{% endfor %}
</table>
Это ссылка на данные, которые я использовал в БД MYSQL.
С приведенным выше кодом я могу получить вывод, подобный приведенной ниже таблице, но я также пытаюсь построить график с фильтрацией по той же дате с временем по оси X и напряжением по оси Y.
да, я сохраняю свои значения в формате даты: «дд-мм-гг», на самом деле я не знаю, как настроить график в jQuery с выбранной осью даты x как время и осью y как напряжение
Начнем с решения проблем с базой данных. Хранение даты и времени в виде строк — плохая идея, поскольку они занимают больше места и не могут обрабатываться так же эффективно, как собственные типы DATE
/TIME
. Дата в виде строки «01-12-2022», хранящаяся в VARCHAR
, использует 11 байтов, тогда как если вы преобразуете ее в DATE
, это всего 3 байта. Аналогично для ваших данных о времени - 8 байтов как VARCHAR
или 3 байта как TIME
. Еще лучше было бы объединить их вместе, так как DATETIME
требуется всего 5 байтов, но я оставлю это вам для размышления.
-- Update dates from dd-mm-yyyy (note 4 digit year) to yyyy-mm-dd
UPDATE `voltage` SET `date` = STR_TO_DATE(`date`, '%d-%m-%Y');
-- If your existing dates have 2 digit year then use
UPDATE `voltage` SET `date` = STR_TO_DATE(`date`, '%d-%m-%y');
-- update the column types
ALTER TABLE `voltage`
MODIFY COLUMN `date` DATE NOT NULL,
MODIFY COLUMN `time` TIME NOT NULL;
Вы также должны убедиться, что у вас есть составной индекс (date
, time
).
Чтобы этот ответ не стал слишком длинным, я не буду включать полное содержимое файла шаблона index.html
, но я внес следующие изменения:
<div id = "purchase_order">
к <div id = "voltages">
<div id = "chart"></div>
перед <div id = "voltages">
<thead>
вокруг строки заголовка и tbody
вокруг остальных строк таблицы.<script src = "https://cdn.plot.ly/plotly-latest.min.js"></script>
после двух скриптов jQuery.From
в from
в разных местах.Затем встроенный скрипт -
<script>
const chartLayout = {
hovermode: 'closest',
xaxis: {
type: 'date',
dtick: 10800000,
hoverformat: '%H:%M:%S',
tickformat: '%H:00\n%d %b',
rangebreaks: [{ pattern: 'hour' }]
}
};
Plotly.react('chart', [{ x: [/* leaving these for you to figure out */], y: [], line: { simplify: false } }], chartLayout);
$(document).ready(function(){
$.datepicker.setDefaults({
dateFormat: 'yy-mm-dd'
});
$(function(){
$("#from").datepicker();
$("#to").datepicker();
});
$('#range').click(function(){
var from = $('#from').val();
var to = $('#to').val();
if (from != '' && to != '')
{
$.ajax({
url:"/range",
method:"GET",
data:{from:from, to:to},
success:function(data)
{
let x = [], y = [], rows = '';
for (const row of data) {
x[x.length] = `${row.date} ${row.time}`;
y[y.length] = row.voltage;
rows += `<tr><td>${row.date}</td><td>${row.time}</td><td>${row.voltage}</td><td>${row.ignition}</td></tr>`;
}
// update table content
$('#voltages > table > tbody').html(rows);
// update chart
Plotly.react('chart', [{ x: x, y: y, line: { simplify: false } }], chartLayout);
}
});
}
else
{
alert("Please Select the Date");
}
});
});
</script>
А это модифицированный /range
маршрут -
@app.route('/range')
def range():
cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
fromDate = request.args.get('from')
toDate = request.args.get('to')
query = """
SELECT CAST(`date` AS CHAR) AS `date`, CAST(`time` AS CHAR) AS `time`, `voltage`, `ignition`
FROM voltage
WHERE date BETWEEN '{}' AND '{}'
ORDER BY date, time
""".format(fromDate, toDate)
cur.execute(query)
voltages = cur.fetchall()
return jsonify(voltages)
date
и time
были преобразованы в CHAR
s в SELECT
, поскольку json.dumps()
(используемый jsonify) не любит обращаться с ними как с их собственными типами. Вам следует переключиться на использование параметризованных подготовленных операторов, чтобы смягчить текущие уязвимости SQLi.
я отредактировал весь свой код, я понял, что выбор даты фильтрует данные с помощью средства выбора даты, способного отображать html-таблицу, не способную получить диаграмму
Большое спасибо, сэр, вы спасли мне жизнь с той недели, когда я борюсь здесь, большое спасибо, сэр.
сэр, изначально график не обновляется, ничего график только пустой, при выборе только диапазона дат он обновляется, можем ли мы установить, что изначально берутся последние 100 записей для создания графика
Plotly.react('chart', [{ x: [/* оставляя это для вас */], y: [], line: {simple: false } }], chartLayout); здесь нужно что-то менять
Да. Я оставил этот комментарий, чтобы сказать вам, что вам нужно сделать. Мы здесь не для того, чтобы писать ваше программное обеспечение для вас, но более чем готовы помочь вам изучить и решить конкретные проблемы. В вашем корневом маршруте вы можете перебирать набор результатов запроса, чтобы создать массивы значений для передачи в ваш шаблон в качестве исходных данных для графика. Попробуйте сделать это самостоятельно, и если вы застряли, опубликуйте новый вопрос (будьте максимально краткими).
согласен с вами, сэр, я попытаюсь понять это сам, спасибо
хорошо, я удалю