I want to create a Python Flask website, in which one webpage shows the bar-chart, another shows the line-chart and lastly the third page shows the timeline. I have got a csv file with Year, Exports and Imports:
1952,8645,8284
1953,9472,8186
1954,11266,9887
1955,13149,12512
1956,15779,14298
Then I have used a datas.py file, which will read the csv and show the csv table in webpage
from flask import Blueprint, current_app, render_template
import os
import csv
datas = Blueprint('datas', __name__)
def read_csv():
data = []
path = os.path.join(
current_app.root_path, os.pardir,
'scraping', 'exports-imports.csv'
)
try:
with open(path, 'r') as f:
reader = csv.reader(f)
for row in reader:
data.append(row)
except FileNotFoundError:
return "Error: CSV file was not found"
return data
@datas.route('/datas')
def show_data():
try:
data = read_csv()
return render_template('datas.html', data=data)
except IOError:
return "The file doesn't exist"
I want to use the function read_csv() and plot the graphs in the page.
from flask import Blueprint, render_template
import matplotlib.pyplot as plt
from .datas import read_csv
graphs = Blueprint('graphs', __name__)
@graphs.route('/line-chart')
def show_line_chart():
data = read_csv()
years = [row[0] for row in data]
exports = [row[1] for row in data]
imports = [row[2] for row in data]
plt.plot(years, exports, label="Exports")
plt.plot(years, imports, label="Imports")
plt.xlabel('Year')
plt.ylabel('Value')
plt.title('Foreign Trade')
plt.legend()
plt.tight_layout()
plt.savefig('static/line-chart.png')
return render_template('line-chart.html')
Lastly line-chart.html:
{% extends "base.html" %}
{% block title %}Line Chart{% endblock %}
{% block content %}
<div >
<h1 >Foreign Trade</h1>
<img src="{{ url_for('static', filename='line-chart.png') }}" alt="Line Chart">
</div>
{% endblock %}
The problem is that it is not creating any img file in the project. Is there any way to build up the image or any other way to solve the problem?
CodePudding user response:
The save image error is mostly due to an error on the path you are given to plt.savefig()
function. Remember that matplot lib doesnt live relative to your app folder. So try given the entire path maybe something like app/static/filename.jpg
Other way of implementing Charts on a flask app is via JavaScript with Libraries like ChartJS or Google Charts.
I'been working on a flask extensions that makes ChartJS integration easy. You could give it a try its in a really early stage tho but suits your problem really well.
You could follow the instructions and repository Here
CodePudding user response:
Finally was able to solve the problem.
import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO
from flask import Blueprint, send_file
from website.datas import read_csv
graphs = Blueprint('graphs', __name__)
@graphs.route('/line-chart')
def show_line_chart():
data = read_csv()
years = [int(row[0]) for row in data]
exports = [int(row[1]) for row in data]
imports = [int(row[2]) for row in data]
fig, ax = plt.subplots()
ax.plot(years, exports, label='Exports')
ax.plot(years, imports, label='Imports')
ax.set_xlabel('Year')
ax.set_ylabel('Value (USD)')
ax.set_title('Foreign Trade')
ax.legend()
buf = BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
return send_file(buf, mimetype='image/png')
And the HTML file looks like this:
{% extends "base.html" %}
{% block title %}Line Chart{% endblock %}
{% block content %}
<div >
<h1 >Foreign Trade</h1>
<img src="/line-chart" alt="Line Chart">
</div>
{% endblock %}
It will create an image in the flask, but it is not hoverable, which needs to be solved.