AJAX jQuery based Chart Example using Python Flask MySQL - python

I am trying to plot charts with MySQL data using ajax for date filtering and plotting chart for filtered data i found this resource https://tutorial101.blogspot.com/2021/01/python-flask-date-range-search-with.html with this resource i can able to filter data using date filter instead of tables in html page i need graph for filtered data how to achive where i can change for ploting graph using plotly or matplotlib
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'] = ''
app.config['MYSQL_DB'] = 'testingdb'
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 orders ORDER BY id 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 orders WHERE purchased_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)
***
CREATE TABLE `orders` (
`id` int(11) NOT NULL,
`customer_name` varchar(100) NOT NULL,
`purchased_items` varchar(100) NOT NULL,
`purchased_date` date NOT NULL,
`price` double(12,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `orders`
--
INSERT INTO `orders` (`id`, `customer_name`, `purchased_items`, `purchased_date`, `price`) VALUES
(1, 'Airi Satou', 'iPhone', '2020-05-07', 649.00),
(2, 'Angelica Ramos', 'Samsung Galaxy', '2020-11-10', 2500.00),
(3, 'Ashton Cox', 'Infinix Note 7', '2020-09-10', 299.09),
(4, 'Bradley Greer', 'Macbook Pro', '2020-11-26', 1799.50),
(5, 'Brenden Wagner', 'Samsung 50\" Smart 4K UHD TV ', '2020-11-27', 479.00),
(6, 'Brielle Williamson', '7 Series Curved LED 4K UHD', '2019-11-27', 269.00),
(7, 'Bruno Nash', 'iMac', '2019-11-28', 1999.05),
(8, 'Caesar Vance', 'Dell Inspiron 3573', '2019-11-30', 1999.05),
(9, 'Cara Stevens', 'Tlc 40inch tv Roku tv', '2019-12-07', 649.00),
(10, 'Cedric Kelly', 'Acer Aspire 3', '2021-01-13', 199.00);
<!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"/>
</head>
<body>
<br/>
<div class="container">
<h2 align="center">Python Flask Date Range Search with jQuery Ajax DatePicker MySQL Database</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">
<tr>
<th width="5%">ID</th>
<th width="35%">Customer Name</th>
<th width="40%">Purchased Item</th>
<th width="10%">Purchased Date</th>
<th width="5%">Price</th>
</tr>
{% for row in orders %}
<tr>
<td>{{row.id}}</td>
<td>{{row.customer_name}}</td>
<td>{{row.purchased_items}}</td>
<td>{{row.purchased_date}}</td>
<td>{{row.price}}</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: '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:"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>
<table class="table table-bordered">
<tr>
<th width="5%">ID</th>
<th width="35%">Customer Name</th>
<th width="40%">Purchased Item</th>
<th width="10%">Purchased Date</th>
<th width="5%">Price</th>
</tr>
{% for row in ordersrange %}
<tr>
<td>{{row.id}}</td>
<td>{{row.customer_name}}</td>
<td>{{row.purchased_items}}</td>
<td>{{row.purchased_date}}</td>
<td>{{row.price}}</td>
</tr>
{% endfor %}
</table>
instead of table on response need graph for purchased item(x-axis) and price(y-axis)
thanks in adavance

Related

update the dropdown without using submit button

Here is a flask application
Use this link to run the application : (Replace XXX with your machine url) http://XXX.0.0.1:5050/?tickers_get=Company2&open_price_get=23
What i am trying is, when the user selects Company2 from the dropdown, the other dropdown should get updated to only 2 prices (22 and 40) without hitting submit button. Then when the user clicks on Submit button, the table should be displayed according
app.py
from flask import Flask, render_template, request
import pandas as pd
import sqlalchemy as sal
from sqlalchemy import create_engine
import pyodbc
import urllib
import numpy as np
app = Flask(__name__)
get_data_through = "manual_entry"
#app.route('/')
def index():
read_df = pd.DataFrame(
[
['Company1', 23, 10000],
['Company2', 22, 40000],
['Company2', 40, 40000]
],
columns=['new_sql_table','Open_price', 'volume']
)
names = set(read_df['new_sql_table'].tolist())
tickers = request.args.getlist('tickers_get')
#tickers_get_to_string = ''.join(tickers) # to convert to string
#open_price_to_filter = np.arange(1000).tolist()
open_price_to_filter = read_df['Open_price'].tolist()
open_price = request.args.getlist('open_price_get')
print(open_price)
open_price_get_to_number = ''.join(open_price)
data = read_df[read_df['new_sql_table'].isin(tickers)]
sum_of_volumns = format(sum(data['volume']), ',')
return render_template('template.html', **locals())
if __name__ == "__main__":
app.run(port = 5050)
template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles/mainpage.css') }}">
<title>Stocks data</title>
</head>
<body>
<h2>Stocks data</h2><h4>Total Volume is : {{sum_of_volumns}} and selected open price is {{open_price_get_to_number}}</h4>
<form>
<label>Company:</label>
<select name="tickers_get">
{% for name in names %}
<option value="{{ name }}" {% if name in tickers %}selected{% endif %}>{{name}}</option>
{% endfor %}
</select>
<label>Open Price:</label>
<select name="open_price_get" style="width:75px">
{% for op in open_price_to_filter %}
<option value="{{ op }}" {% if op in open_price %}selected{% endif %}>{{op}}</option>
{% endfor %}
</select>
<button type="submit">Submit</button>
</form>
<hr/>
<table border="2" width="100%">
<thead>
<tr>
{% for column in data.columns %}
<th>{{ column }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in data.values %}
<tr style="text-align:center">
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
I am not able to get the dynamic dropdown in the second filter
In order to dynamically fill your second select box with data depending on the first, you need JavaScript.
In the following example, an event listener is registered for the first input field, which responds to events of type change. If the selection changes within this field, the required data is obtained asynchronously from a second endpoint and inserted into the second input field. The Fetch API is used for this, which receives the data in JSON format.
The ticker symbols will be sent in a comma separated string via GET request. This means that these are transferred as URL parameters, i.e. appended to the URL. With the query request.arg.get(...) the values are queried based on their name. The default is an empty list. In the lambda expression, the string is separated by commas and empty values are filtered out by a loop. You will get a list of ticker symbols.
symbols = request.args.get(
'symbols', # Name of parameter
[], # Default return value
type=lambda x: [y for y in x.split(',') if y] # Split by ',' and filter empty strings
)
All rows whose "Symbol" column is contained in the list are then filtered out of the DataFrame. The "Open Price" column is extracted from these rows and any duplicates are prevented by a set.
open_prices = set(df[df['Symbol'].isin(symbols)]['Open Price'].tolist())
Finally, the received prices are returned as a list in JSON format, contained within a nested structure called "items".
return jsonify(items=list(open_prices))
When the form is finally sent, the data required for display is filtered from the DataFrame and passed to the template.
from flask import (
Flask,
jsonify,
render_template,
request
)
import pandas as pd
df = pd.DataFrame(
[
['Company1', 23, 10000],
['Company2', 22, 40000],
['Company2', 40, 40000],
],
columns=['Symbol','Open Price', 'Volume']
)
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
symbols = set(df['Symbol'].tolist())
open_prices = set(df['Open Price'].tolist())
sel_symbols = symbols
sel_open_prices = open_prices
if request.method == 'POST':
sel_symbols = request.form.getlist('symbols')
sel_open_prices = request.form.getlist('open-prices', type=int)
open_prices = set(df[df['Symbol'].isin(sel_symbols)]['Open Price'].tolist())
data = df[df['Symbol'].isin(sel_symbols)][df['Open Price'].isin(sel_open_prices)]
total_volumes = sum(data['Volume'])
return render_template('index.html', **locals())
#app.route('/open-prices')
def open_prices():
symbols = request.args.get('symbols', [], type=lambda x: [y for y in x.split(',') if y])
open_prices = set(df[df['Symbol'].isin(symbols)]['Open Price'].tolist())
return jsonify(items=list(open_prices))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
<style type="text/css">
table, th, td {
border: 1px solid #9a9a9a;
border-collapse: collapse;
padding: .64rem;
}
th {
border-bottom: 2px solid #9a9a9a;
}
select {
width: 75px;
}
</style>
</head>
<body>
<form method="POST">
<label for="symbols">Symbol</label>
<select name="symbols" id="symbols" multiple>
{% for symbol in symbols -%}
<option value="{{ symbol }}" {% if symbol in sel_symbols %}selected{% endif %}>{{ symbol }}</option>
{% endfor -%}
</select>
<label for="open-prices">Open Price</label>
<select name="open-prices" id="open-prices" multiple>
{% for price in open_prices -%}
<option value="{{ price }}" {% if price in sel_open_prices %}selected{% endif %}>{{ price }}</option>
{% endfor -%}
</select>
<button type="submit">Submit</button>
</form>
<hr />
{% if data.values | count -%}
<h4>Total Volume is {{total_volumes}} and selected
{{ 'are' if sel_open_prices | count > 1 else 'is'}}
{{ sel_open_prices | join(', ') }}.
</h4>
<table width="100%">
<thead>
<tr>
{% for column in data.columns %}
<th>{{ column }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in data.values %}
<tr style="text-align:center">
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% else -%}
<p>No items found.</p>
{% endif -%}
<script type="text/javascript">
(function(url) {
const priceSelect = document.querySelector('select[name="open-prices"]');
const tickerSelect = document.querySelector('select[name="symbols"]');
tickerSelect && tickerSelect.addEventListener('change', function(event) {
// Get selected items.
let optionsSelected = [];
let options = event.target.options;
for (let opt of options) {
if (opt.selected) {
optionsSelected.push(opt.value || opt.text);
}
}
// Send AJAX request to the server.
fetch(`${url}?symbols=${encodeURIComponent(optionsSelected.join(','))}`)
.then(resp => resp.ok && resp.json())
.then(data => {
// Add the entries to the input field.
priceSelect && (priceSelect.innerHTML = data.items.map(item => {
return `<option value="${item}" selected>${item}</option>`;
}).join(''))
});
});
})({{ url_for('open_prices') | tojson }});
</script>
</body>
</html>

How to take the value from the field and send it to the Flask code for use in the updated page

Have a good day!
I don't know much about Flask
I try to depict insert several (two) objects on the page and embed add the ability (so that you can) update these objects.
There is a main element on the page - the choice of a date range.
When you select a start date and an end date and click the button in the same way (two objects should be updated).
The first object is a table. The table (object) is updated.
The second object is a graph. This object is not updated.
What can be done to update the second object (chart)?
I would be extremely grateful for any help.
It's HTML
<div class="row">
<div class="col-md-3">
<input type="text" name="From" id="From" class="form-control" placeholder="From Date"/>
</div>
<div class="col-md-3">
<input type="text" name="to" id="to" class="form-control" placeholder="To Date"/>
</div>
<div class="col-md-6">
<input type="button" name="range" id="range" value="Range" class="btn btn-success"/>
</div>
</div>
<div id="purchase_order"></div>
<hr>
<div class="row" style="align-content: center">
<div class="text" style="align-content: center">
</div>
<div class="outer-wrapper" style="align-content: center">
<div class="table-wrapper" id="table-wrapper" style="align-content: center">
<table>
<thead>
{% for col in column_names %}
<th>{{col}}</th>
{% endfor %}
</thead>
<tbody>
{% for row in row_data %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-md-1">
</div>
<div class="col-md-10">
<div>
<canvas id="myChart" width="800px" style="align-content: center"></canvas>
</div>
</div>
<div class="col-md-1">
</div>
</div>
it's script
<script>
$(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:"POST",
data:{From:From, to:to},
success:function (data)
{
$('#table-wrapper').html(data);
$('#table-wrapper').append(data.htmlresponse);
}
});
$.ajax({
url:"/range2",
method:"POST",
data:{From:From, to:to},
success:function (data)
{
$('#myChart').html(data);
$('#myChart').append(data.htmlresponse2);
}
});
}
else
{
alert("Please Select the Date")
}
});
});
</script>
it's Flask code
#app.route('/', methods=['GET','POST'])
#app.route('/index')
def home_page(): # put application's code here
if request.method=="POST":
upload_excel=request.files['upload_excel']
if upload_excel.filename != '':
filepath=os.path.join(app.config["UPLOAD_FOLDER"],upload_excel.filename)
upload_excel.save(filepath)
data=pd.read_excel(upload_excel)
data.to_sql('kotel', con=db.engine, if_exists="append", index=False)
return print(data)
df = pd.read_sql('select * from kotel', con=db.engine)
df['date'] = df['date'].dt.round('2min')
y_data = df['tnv'].tolist()
x_data = df['date'].tolist()
print(y_data)
type(y_data)
print(x_data)
df_graph = df.copy()
df_graph.drop(df_graph.columns[[0, 1, 2]], axis=1, inplace=True)
print(df_graph)
# df['date'] = pd.to_datetime(df['date'], format="%Y.%d.%B %H")
return render_template('index new.html', column_names=df.columns.values, row_data=list(df.values.tolist()), column_names_graph=df_graph.columns.values, os_y = y_data, os_x = x_data)
#app.route("/range", methods=["POST","GET"])
def range():
if request.method == 'POST':
From = request.form['From']
to = request.form['to']
df = pd.read_sql('select * from kotel', con=db.engine)
df['date'] = pd.to_datetime(df['date'])
df = df.loc[(df['date'] >= From) & (df['date'] <= to)]
df['date'] = df['date'].dt.round('2min')
return jsonify({'htmlresponse': render_template('response.html', column_names=df.columns.values, row_data=list(df.values.tolist()))}), df
#app.route("/range2", methods=["POST","GET"])
def range2():
df_new = pd.read_sql('select * from table_1', con=db.engine)
y_data = df_new['temper'].tolist()
x_data = df_new['rashod'].tolist()
return jsonify({'htmlresponse2': render_template('response2.html', os_y = y_data, os_x = x_data)})
it's extended html 1 add
<table>
<thead>
{% for col in column_names %}
<th>{{col}}</th>
{% endfor %}
</thead>
<tbody>
{% for row in row_data %}
<tr>
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
it's extended html 2 add
<script>
const labels = [{% for item in os_x %}
"{{ item }}",
{% endfor %}];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [{% for item in os_y %}
{{ item }},
{% endfor %}],
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
</script>
<script>
const myChart = new Chart(
document.getElementById('myChart'),
config
);
</script>
I would really like to be able (so that I can) take a value variable from a form field (dropdown ) and send it to the Flask code so that I can use it in the updated page.
image screen
image screen

how can AJAX dynamically add rows to a table

I was wondering if someone could help me figure out how to add rows to the following html dynamically using AJAX whenever a database query finds more records. I am using python flask and pandas to create a dataframe with nodes information such as when a node is ACTIVE, or in SLEEP mode, LOCKED or UNLOCKED. I was thinking that I could somehow pass that dataframe and iterate through it to create a table with that information and a link to another page for that specific node. Now,I think I have the first part down where I am POSTing the page when it is first brought up with all of the recorded nodes. But I think I'm doing that part wrong too. I suppose I have two questions then:
How can I pass a dataframe to the html and iterate through it correctly?
How can I use AJAX to add another row to the table whenever any other node that registers? I was thinking maybe I pass a list of nodeID's to the HTML when I POST and then have setInterval pass that to the python flask side, query the database, create a new list and compare..removing those that I already added, pass the dataframe of those that are new to AJAX function along with a full list of NodeID's....does that sound right?
So far I was only able to figure this out for a POST but no idea what to do next:
HTML
<div class="container">
<h2>Incubator List</h2>
<p>List of Registered Encubators:</p>
<table class="table table-dark table-striped">
<thead>
<tr>
<th>NodeID</th>
<th>Last Update</th>
<th>Status</th>
<th> </th>
<th>Control Link</th>
</tr>
</thead>
{% for node in nodes %}
<tr>
<td>{{ node.NodeID }}</td>
<td>{{ node.last_update }}</td>
{% if {{ node.Sleep }} == "True" %}
<td><p class="bg-secondary text-white text-center">SLEEP</p>></td>
{% else %}
{% if {{ node.Active }} == "True" %}
<td><p class="bg-success text-white text-center">ACTIVE</p></td>
{% else %}
<td><p class="bg-danger text-white text-center">NOT ACTIVE</p>></td>
{% endif %}
{% endif %}
{% if {{ node.LOCK }} == "True" %}
<i class="fas fa-lock"></i>
{% else %}
<i class="fas fa-unlock"></i>
{% endif %}
<td>
<form action="/nodeslist" METHOD = "POST">
<input type="hidden" id="NodeID" name="NodeID" value={{ node.NodeID }}>
<input TYPE="SUBMIT" value="Access" class = "btn btn-success">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
function UPDATEnodelist(nodeIDlist) {
$.get('/nodeDHT?nodeIDlist ='+nodeIDlist ,
function(data){
const parsed = JSON.parse(data)
nodeIDlist = parsed.nodeIDlist;
something-pandas-dataframe-something;
};
)
};
setInterval(function () {
UPDATEnodelist(nodeIDlist);
return false;
}, 2500);
</script>
{% endblock content %}
python flask
#app.route('/nodeslist', methods=['POST','GET'])
def nodelist():
df= DAO.Pull_Type_Nodes()
if request.method == "POST":
title='List of Registered Nodes')
nodeIDlist = nodes.NodeID.unique()
nodes = df.to_json(orient ='records')
return render_template('nodeslist.html',title=title, nodes=nodes, nodeIDlist=nodeIDlist)
else:
oldnodeIDlist = request.form['NodeID']
add_df = df[~df['NodeID'].isin(oldnodeIDlist)]
new_nodes = add_df.to_json(orient ='records')
return new_nodes,nodeIDlist
Please any help would be greatly appreciated!
EDIT:
The response should be a dataframe with fields 'nodeID','sleep' (bool), 'lock' (bool), 'active' (bool)
<table id="table" class="table table-dark table-striped">
<thead>
<tr>
<th>NodeID</th>
<th>Last Update</th>
<th>Status</th>
<th></th>
<th>Control Link</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<form action="/nodeslist" METHOD="POST">
<input type="hidden" id="NodeID" name="NodeID" value={{ node.NodeID }}>
<input TYPE="SUBMIT" value="Access" class="btn btn-success" id="btn">
</form>
</td>
</tr>
</tbody>
</table>
const date = new Date();
const data = [...Array(10).keys()].map(id => {
return {
id: id+1,
date: new Date((Math.random() * 10000000) + date.getTime()).toLocaleString(),
status: Math.floor(Math.random() * 2),
};
});
const tbody = document.querySelector('#table').querySelector('tbody');
function test(evt) {
evt.preventDefault();
let fragment = document.createDocumentFragment();
data.forEach(d => {
let tr = document.createElement('tr');
Object.keys(d).forEach(x => {
let td = document.createElement('td');
let textNode = document.createTextNode(d[x]);
td.appendChild(textNode);
tr.appendChild(td);
})
fragment.appendChild(tr);
});
tbody.appendChild(fragment);
}
document.querySelector('#btn').onclick = test;
Here working example

Python Requests, Successful website log in but redirects me to log in page

I am trying to scrape a website using Python's Requests Module
It's a website we can only access inside our company.
Every time I try to scrape the website using get(), it show's this
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Authorization Required</title>
</head><body>
<h1>Authorization Required</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.2.13 (Red Hat) Server at tcfabcert Port 80</address>
</body></html>
But when I insert the auth=('user','pass'), it get's a respone of 200 but it doesn't log me in and every time I try to log in using post() method it just keeps redirecting me to the same Login Page.
Here is my code:
import requests
payload = {'userID': 'user',
'password': 'mypass',
'userLocale': 'US CA',
'userBU': 'MB',
'servName': 'Certification',
'login': 'Login',
'rememberFlag': 'false',
'hiddenHost': 'cpc44743'}
cookie = {'Cookie': 'JSESSIONID=AF1A7CC747492C3D4259B230A5F7635A.PKYCUbG8Dba7VqoxAzD4WA'}
header = {'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate',
'Accept-Language':'en-US,en;q=0.9',
'Cache-Control':'max-age=0',
'Connection':'keep-alive',
'Content-Length':'138',
'Content-Type':'application/x-www-form-urlencoded',
'Cookie':'JSESSIONID=AF1A7CC747492C3D4259B230A5F7635A.PKYCUbG8Dba7VqoxAzD4WA',
'Host':'tcfabcert',
'Origin':'http://tcfabcert',
'Referer':'http://tcfabcert/ws/ess/default.jsp',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'}
with requests.Session() as r:
url = "http://tcfabcert/ws/ess/"
res = r.get(url, auth=('user', 'password')).text
res2 = r.post(url, auth=('user', 'password'), datas=payload, headers=header, allow_redirects=True)
Here is the code of the log in page
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta name="GENERATOR"
content="IBM WebSphere Page Designer V3.5.2 for Windows" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>Editorial System</title>
<link rel="stylesheet" type="text/css" href="/ws/ess/theme/Style2.css" />
<script type="text/javascript">
var GB_ROOT_DIR = "/ws/ess/greybox/";
</script>
<script type="text/javascript" src="/ws/ess/greybox/AJS.js"></script>
<script type="text/javascript" src="/ws/ess/greybox/AJS_fx.js"></script>
<script type="text/javascript" src="/ws/ess/greybox/gb_scripts.js"></script>
<link href="/ws/ess/greybox/gb_styles.css" rel="stylesheet" type="text/css" media="all" />
<script language="JavaScript1.2">
<!-- Hide from older browsers
// Original JavaScript code by Duncan Crombie: dcrombie at chirp.com.au
// Please acknowledge use of this code by including this header.
function getCookie(name) { // use: getCookie("name");
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return (value != null) ? unescape(value[1]) : null;
}
var today = new Date();
var expiry = new Date(today.getTime() + 28 * 24 * 60 * 60 * 1000); // plus 28 days
function setCookie(name, value) { // use: setCookie("name", value);
document.cookie=name + "=" + escape(value) + "; expires=" + expiry.toGMTString();
}
// Stop hiding -->
function dispHandle(obj) {
if (obj.style.display == "none")
obj.style.display = "";
else
obj.style.display = "none";
}
</script>
<script language="JavaScript1.2">
function rememberMe(cbox)
{
userIDValue = document.forms(0).userID.value;
userPWDValue = document.forms(0).password.value;
userLocale = document.forms(0).userLocale.value;
userBU = document.forms(0).userBU.value;
if (cbox.checked)
{
document.forms(0).rememberFlag.value = "true";
setCookie("userID", userIDValue);
setCookie("userPWD", userPWDValue);
setCookie("userLocale", userLocale);
setCookie("userBU", userBU);
}
}
//function to reset the locale/bu
function setUserLocale(userLocale, userBU)
{
setCookie("userBU", userBU);
setCookie("userLocale", userLocale);
document.forms(0).submit();
}
function submitForm() {
userIDValue = new String();
userIDValue = document.forms(0).userID.value;
userPWDValue = document.forms(0).password.value;
userLocale = document.forms(0).userLocale.value;
userBU = document.forms(0).userBU.value;
rFlag = document.forms(0).rememberFlag.value;
if (document.forms(0).password.value.length <1)
{
//alert("Please enter password");
//alert("Please enter password");
}
else if (rFlag = "true")
{
setCookie("userID", userIDValue);
setCookie("userPWD", userPWDValue);
setCookie("userLocale", userLocale);
setCookie("userBU", userBU);
}
document.forms(0).submit();
}
function _HpbJumpURL(url)
{
if (url != '')
{
window.location = url;
}
}
function checkBrowser(){
var userID=getCookie("userID");
var userPWD = getCookie("userPWD");
var userLocale = getCookie("userLocale");
var userBU = getCookie("userBU");
if (userID != null && userPWD != null)
{
document.forms(0).userID.value = userID;
document.forms(0).password.value = userPWD;
}
this.ver=navigator.appVersion
this.dom=document.getElementById?1:0
//Changes made by ANANDA5 for IE8 Migration
//this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom)?1:0;
this.ie8=(this.ver.indexOf("MSIE 8")>-1 && this.dom)?1:0;
//End
var hName= window.location.host;
var hPlatform = "";
if (hName.indexOf("cert") != -1 )
{
hPlatform = "Certification";
}
else if (hName.indexOf("prod") != -1)
{
hPlatform = "Production";
}
else if (hName.indexOf("int") != -1)
{
hPlatform = "Development";
}
else if (hName.indexOf("lngcentral") != -1)
{
hPlatform = "Production";
}
else
{
hPlatform = "Development";
}
document.login.servName.value=hPlatform;
return this
}
function addToFavorites()
{
window.external.AddFavorite(window.url, "EdSched");
}
function showNew()
{
var userBU = getCookie("userBU");
if (userBU != null && userBU != "LNFR")
{
var newPage=getCookie("newPage3-17");
if (newPage == null || newPage=="TRUE")
{
whatsNew =GB_showFullScreen("What's new for this Release","../whatsnew.jsp");
}
}
}
</script>
</head>
<body onload="checkBrowser(); showNew();">
<form name="login" method="post" action="/ws/ess/default.jsp"><!-- Set the Default Locale -->
<br>
<br>
<br>
<center>
<table style='background: #dae0d2 url("images/bg.gif") repeat-x bottom; border: 1px thin'>
<tbody>
<tr>
<td align="center"><img src="/ws/ess/images/edsched.png" border="0"></td>
</tr>
<tr>
<td align="center"><label class="TextLabel4">(Editorial Scheduling System)</label> <br>
<br>
</td>
</tr>
<tr>
<td align="center"><label class="TextLabel4">Enter the Login Details</label> <br>
</td>
</tr>
</tbody>
</table>
</center>
<center>
<table style='background: #dae0d2 url("images/bg.gif") repeat-x bottom; border: 1px thin'>
<tbody>
<tr>
<td>
<div id="userDetails">
<center>
<table>
<tbody>
<tr class="EbTopBar">
</tr>
<tr class="EbTopBar">
<td align="right" width="100"><label class="TextLabel1">UserId :</label></td>
<td width="110"><input type="text" name="userID" value=""
class="EbInputBg" size="15" tabindex="1"></td>
</tr>
<tr class="EbTopBar">
<td align="right" width="100"><label class="TextLabel1">Password :</label></td>
<td width="110"><input type="password" name="password" value=""
class="EbInputBg" size="15" tabindex="2"></td>
</tr>
</tbody>
</table>
</center>
</div>
</td>
</tr>
<tr>
<td>
<div style="display:" id="vanisher">
<center>
<table>
<tbody>
<tr class="EbTopBar">
<td align="right" width="100"><label class="TextLabel1">Location</label></td>
<td width="110"><select id="userLocale" name="userLocale"
class="ComboBox_ID12">
<OPTION value="US CA" >US CA</OPTION>
<OPTION value="FR" >FR</OPTION>
<OPTION value="AU" >AU</OPTION>
<OPTION value="SNG" >SNG</OPTION>
<OPTION value="LNC" >LNC</OPTION>
</select></td>
</tr>
<tr class="EbTopBar">
<td align="right" width="100"><label class="TextLabel1">Business Unit</label></td>
<td width="110"><select id="userBU" name="userBU"
class="ComboBox_ID12">
<OPTION value="LNC" >LNC</OPTION>
<OPTION value="COS" >COS</OPTION>
<OPTION value="MI" >MI</OPTION>
<OPTION value="MB" >MB</OPTION>
<OPTION value="MDC-SNG" >MDC-SNG</OPTION>
<OPTION value="LNFR" >LNFR</OPTION>
</select></td>
</tr>
<tr class="EbTopBar">
<td/>
<td align="left" width="100"><label class="TextLabel1">Correct business unit must be selected</label></td>
</tr>
</tbody>
</table>
</center>
</div>
</td>
</tr>
<!--
<TR>
<TD CLASS="link"><A HREF="javascript:dispHandle(vanisher)">Choose
Language </A></TD>
</TR>
-->
<tr>
<td>
<center>
<table>
<tbody>
<tr>
<td align="right" width="100"><label class="TextLabel1">Platform :</label></td>
<td width="110"><input type="text" name="servName" value=""
class="EbReadOnly" size="15" tabindex="3" readonly></td>
</tr>
<tr>
<td align="right" width="100"></td>
<!--
<TD WIDTH="110"><INPUT TYPE="checkbox" NAME="rememberme" VALUE="N"
ONCLICK="rememberMe(this);"><LABEL CLASS="TextLabel1">Remember Me</LABEL></TD>
-->
</tr>
</tbody>
</table>
</center>
</td>
</tr>
<tr>
<td>
<center>
<table id="loginButtons">
<tbody>
<tr>
<td width="80"></td>
<td><input type="submit" name="login"
value='Login'
onclick="submitForm()" class="EbButton" /></td>
<td><input type="reset" name="cancel"
value='Cancel' class="EbButton" /></td>
<td width="80"></td>
</tr>
</tbody>
</table>
</center>
</td>
</tr>
</tbody>
</table>
</center>
<input type="hidden" name="rememberFlag" value="false">
<center>Login problems?<br>
</center>
<center>
<table border="1">
<tbody align="center">
<tr>
<td align="center">English</td>
<td align="center"><a href="javascript:setUserLocale('FR', 'LNFR')";>Français</a></td>
</tr>
</tbody>
</table>
</center>
<input name="hiddenHost" type="hidden" value='cpc44743'/>
</form>
</body>
</html>

How do I use Flask to show a generated matplotlib image on the same screen as the form?

Basically I am using matplotlib to generate charts that I want to then display directly to the user. The user fills out a form and the variables are passed to a few methods that create the chart. The code I currently have will show only the image and get rid of the form. Is it possible to display the image on the page so that the user can modify the queries/connections and see the results with each subsequent form submission?
Here is my code:
from flask import Flask, request, render_template, send_file, redirect, url_for
import flask
import MultipleDatabasesLib as mdl
import subprocess
import pandas as pd
import matplotlib as plt
from matplotlib import pyplot as plt
app = Flask(__name__)
xlabel = ""
ylabel = ""
graph_title = ""
#app.route('/')
def my_form():
return render_template('my-form.html')
#app.route('/get_form_vals', methods=['POST', 'GET'])
def form_vals():
df = pd.DataFrame()
df_group = pd.DataFrame()
fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 15
fig_size[1] = 12
plt.rcParams["figure.figsize"] = fig_size
base = "C:/Python36-32/GraphFactory/Final_csv.csv"
conn1 = flask.request.args.get('conn1')
conn2 = flask.request.args.get('conn2')
sql1 = flask.request.args.get('sql1')
sql2 = flask.request.args.get('sql2')
charttype = flask.request.args.get('charttype')
xlabel = flask.request.args.get('xLabel')
ylabel = flask.request.args.get('yLabel')
groupBy = flask.request.args.get('groupBy')
#graph_title = charttype + "Chart"
mdl.gen_csv(conn1, conn2, sql1, sql2)
df = pd.read_csv(base)
df_group = df.groupby(['YR', 'INSTANCE']).size()
if charttype == "bar":
mdl.bar_plot(xlabel, ylabel, 'Plot', df_group)
elif charttype == "pie":
mdl.pie_plot(xlabel, ylabel, 'Plot', df_group)
elif charttype == "line":
mdl.line_plot(xlabel, ylabel, 'Plot', df_group)
elif charttype == "hist":
mdl.hist_plot(xlabel, ylabel, 'Plot', df_group)
#return send_file("plt.png", mimetype='image/gif')
return flask.jsonify({"result":"<div class='user_avatar' style='background-image:url('/static/images/figure.png');width:240px;height:240px;background-size:cover;border-radius:10px;'>"})
app.run(host='0.0.0.0', port=33)
HTML:
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="/static/my-css.css">
<head>
<meta charset="UTF-8">
<title>Graph Factory</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<table class="headerTable" background="https://crunchify.com/bg.png" width="100%">
<tr>
<td width="95%"><img src="static/SEILogo.png" /></td>
</tr>
</table>
<table style="width:50%" class="inputForm" align="center" cellspacing="0">
<tr>
<th>
Connection
</th>
<th>
Query
</th>
</tr>
<tr>
<td align="center">
<input type="text" name="conn1" id="conn1"/>
</td>
<td align="center">
<textarea name="sql1" cols="70" rows="8" id="sql1"></textarea>
</td>
</tr>
<tr>
<td align="center">
<input type="text" name="conn2" id="conn2"/>
</td>
<td align="center">
<textarea name="sql2" cols="70" rows="8" id="sql2"></textarea>
</td>
{#<td align="left">
Export CSV
</td>#}
</tr>
<tr class="top row">
<td align="center">
<label>X-axis Label</label>
</td>
<td align="center">
<input type="text" name="xLabel" id="xLabel"/>
</td>
</tr>
<tr>
<td align="center">
<label>Y-axis Label</label>
</td>
<td align="center">
<input type="text" name="yLabel" id="yLabel"/>
</td>
</tr>
<tr>
<td align="center">
<label>Group by Parameter</label>
</td>
<td align="center">
<input type="text" name="groupBy" id="groupBy"/>
</td>
</tr>
<tr>
<td align="center">
<label>Graph Type</label>
</td>
<td align="center">
<select name="charttype" id="dropdownchart">
<option value="bar">Bar</option>
<option value="pie">Pie</option>
<option value="line">Line</option>
<option value="hist">Hist</option>
</select>
</td>
</tr>
<tr>
<td colspan="20" align="center">
<button type='button' class='get_result'>Show Graph</button>
</td>
</tr>
</table>
<div id='image_location'></div>
<script>
$(document).ready(function() {
$('.get_result').click(function(){
var conn1 = $('#conn1').val();
var conn2 = $('#conn2').val();
var sql1 = $('#sql1').val();
var sql2 = $('#sql2').val();
var xlabel = $('#xLabel').val();
var ylabel = $('#yLabel').val();
var groupBy = $('#groupBy').val();
var dropdownchart = $('#dropdownchart').val();
$.ajax({
url: "/get_form_vals",
type: "get",
data: {conn1: conn1, conn2:conn2, sql1:sql1, sql2:sql2, xlabel:xlabel, ylabel:ylabel,
groupBy:groupBy, dropdownchart:dropdownchart},
success: function(img) {
$("#image_location").html(img.result);
},
error: function(xhr) {
print("error")
}
});
});
});
</script>
</body>
</html>
You will have to use flask with ajax. To do that, you will need to create a separate route to create the graph, savee the file, and return the HTML with the link to the image. Below is a slightly shortened solution showing how this can be done. Ensure that you have a static/images directory created, with static at the same level as templates/ in your application folder:
in main_app.py:
import matplotlib.pyplot as plt
import flask
app = flask.Flask(__name__
#app.route('/', methods=['GET'])
def home():
return render_template('my-form.html')
#app.route('/get_form_vals')
def form_vals():
conn1 = flask.request.args.get('conn1')
conn2 = flask.request.args.get('conn2'])
#rest of vals follow
plt.plot(x, y) #formulate your x, y values before
plt.savefig('/app/static/images/filenameXYZ.png') #save to the images directory
return flask.jsonify({"result":"<div class='user_avatar' style='background-image:url('/static/images/figure.png');width:240px;height:240px;background-size:cover;border-radius:10px;'>"})
Then, in my-form.html:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<input type='text' id='conn1'>
<input type='text' id='conn2'>
<!--rest of inputs follow -->
<button type='button' class='get_result'></button>
<div id='image_location'></div>
<script>
$(document).ready(function() {
$('.get_result').click(function(){
var conn1 = $('#conn1').val();
var conn2 = $('#conn2').val();
//get the rest of the vals
$.ajax({
url: "/get_form_vals",
type: "get",
data: {conn1: conn1, conn2:conn2}, //fill out rest of object
success: function(response) {
$("#image_location").html(response.message);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
</html>

Categories