How to display image in django using HttpResponse - python

I am trying to display the image of python script output using below lines but instead of displaying in browser, code downloading the file instead of displaying
this is the function i have created in views.py:
def adc(request):
file = "C:\Users\TheBoss\Downloads\New_test.xlsx"
df = pd.read_excel(file, sheet_name='Graph')
plt.plot(df['Date'], df['Video Device - Not Responding'], label = 'Video Device - Not Responding')
#plt.plot(df['Date'], df['30th Apr'], 'b', label = '30-Apr')
plt.xticks(rotation=45)
plt.tick_params(axis='x', which='major', labelsize=6)
# naming the y axis
plt.ylabel('Condition Count')
# giving a title to my graph
plt.title('Condition')
# function to show the plot
plt.legend()
#plt.show()
plt.savefig('C:\\Users\\TheBoss\\Downloads\\test.png')
image_data = open("C:\\Users\\TheBoss\\Downloads\\test.png", "rb").read()
return HttpResponse(image_data, content_type="test/png")

Generally, this should be enough to display image inline.
def adc(request):
file = "C:\Users\TheBoss\Downloads\New_test.xlsx"
df = pd.read_excel(file, sheet_name='Graph')
plt.plot(df['Date'], df['Video Device - Not Responding'], label = 'Video Device - Not Responding')
plt.xticks(rotation=45)
plt.tick_params(axis='x', which='major', labelsize=6)
plt.ylabel('Condition Count')
plt.title('Condition')
plt.legend()
buffer = io.BytesIO()
plt.savefig(buffer, format='png')
return HttpResponse(buffer.getvalue(), content_type="test/png")
It should display as an image in most browsers and if you want to insert the image in HTML, you'd use a simple
<img src="{% url 'my_image' %}">
I know from experience that this works in Edge, Firefox and Opera. Sometimes browsers need additional convincing to display image inline and in those cases setting the header Content-Disposition to inline usually works.

Related

How to fix size problems using flask and matplotlib to generate plots?

enter image description hereI am setting up a web application and I want to be able to make plots using matplotlib and flask. For one of the plots, I had to use "plt.tight_layout()" to be able to read the labels. My problem now is that I would to adjust the size of the plots to have the same dimensions in the y axis in both of them.
I am using a Python 2.7.16 anaconda enviroment on macOS Mojave (Version 10.14.4).
I have tried to use the following functions:
plt.rcParams["figure.figsize"] = (5,1)
plt.figure(figsize=(5,1))
The only function that worked was:
plt.gcf().set_size_inches(9.0, 1.78)
but I am not able to set it up manually
from flask import Flask, request, redirect, g, render_template
import requests
import base64
from cStringIO import StringIO
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
app = Flask(__name__)
#app.route("/callback/")
def song_analysis():
# Making a plot
img = StringIO()
plt.scatter(names,valence, color=[ 'deeppink','lightpink','lime','orange','blue','green','red','cyan','magenta','yellow','black','white','wheat', 'black', 'indigo', 'snow', 'orchid', 'steelblue', 'grey','aqua'])
plt.xticks([])
plt.tight_layout()
plt.savefig(img,format='png')
plt.close()
img.seek(0)
plot_url = base64.b64encode(img.getvalue())
img2= StringIO()
plt.scatter(names,speechiness, color=[ 'deeppink','lightpink','lime','orange','blue','green','red','cyan','magenta','yellow','black','white','wheat', 'black', 'indigo', 'snow', 'orchid', 'steelblue', 'grey','aqua'])
plt.xticks(rotation=90)
plt.tight_layout()
plt.savefig(img2,format='png')
plt.close()
img2.seek(0)
plot_url2 = base64.b64encode(img2.getvalue())
return render_template("index.html", info_name = [display_name], plot_url=plot_url, plot_url2=plot_url2)
if __name__ == "__main__":
app.run(debug=True,port=PORT)
Including these lines in the html file:
<img src="data:image/png;base64, {{ plot_url }}" width="800">
<img src="data:image/png;base64, {{ plot_url2 }}" width="800">

How to access graph which is present in views.py file into html templates in django

I have a views.py file as follows
def showimage(request):
# Construct the graph
t = arange(0.0, 2.0, 0.01)
s = sin(2*pi*t)
plot(t, s, linewidth=1.0)
xlabel('time (s)')
ylabel('voltage (mV)')
title('About as simple as it gets, folks')
grid(True)
buffer = StringIO.StringIO()
canvas = pylab.get_current_fig_manager().canvas
canvas.draw()
pilImage = PIL.Image.frombytes("RGB", canvas.get_width_height(), canvas.tostring_rgb())
pilImage.save(buffer, "PNG")
pylab.close()
Could you please help me to pass that graph into the html page?
It looks like you copied your code directly from https://www.eriksmistad.no/making-charts-and-outputing-them-as-images-to-the-browser-in-django/ but without the imports and definition.
You also left off the ending:
# Send buffer in a http response the the browser with the mime type image/png set
return HttpResponse(buffer.getvalue(), content_type="image/png")
But I wouldn't put this directly in my views.

Two functions in Flask to plot data independently

How do I create separate functions (within index function in the controller.py) so I can create two independent plots with two independent files that I load independently?
In other words, I would like the user take the following steps:
Upload the Training file
Click the 'Plot' button to plot
Now upload the Test file
Click the 'Plot' button to plot.
Both plots should appear on the same HTML template. Both files will use the same plotting function (or now). Ideally, I would like to use different functions.
Here's how the input HTML looks like:
The function to plot is the following:
def compute_mean_std(filename=None):
# data = np.loadtxt(os.path.join('uploads', filename))
df = pd.read_csv(os.path.join('uploads', filename))
sns.set_style('darkgrid')
fig, ax = plt.subplots(3, sharex=True)
ax[0].plot(df.index, df.x, color="red")
ax[1].plot(df.index, df.y, color="blue")
ax[2].plot(df.index, df.z, color="teal")
ax[0].legend(numpoints=1, loc=1)
ax[1].legend(loc=1)
ax[2].legend(loc=1)
# Check static folder:
if not os.path.isdir('static'):
os.mkdir('static')
else:
for plotfilename in glob.glob(os.path.join('static', '*.png')):
os.remove(plotfilename)
plotfile = os.path.join('static', str(time.time()) + '.png')
plt.savefig(plotfile)
return plotfile
While the controller has the following code:
from compute import compute_mean_std as compute_function
#app.route('/', methods=['GET', 'POST'])
def index():
form = Average(request.form)
filename = None # default
if request.method == 'POST':
# Save uploaded file on server if it exists and is valid
if request.files:
file = request.files[form.filename.name]
if file and allowed_file(file.filename):
# Make a valid version of filename for any file ystem
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'],
filename))
result = compute_function(filename)
else:
result = None
return render_template("view.html", form=form, result=result)
Right now both plot the same plots.
So How do we differentiate the two file uploads.? The option is we have to create two file input...
<input type="file" name="file_training">
<input type="file" name="file_test">
and in your view function you have to check which file is user uploaded
# Inside POST method
file_training = request.files.get('file_training')
file_test = request.files.get('file_test')
return jsonify({"file_training": file_training, "file_test": file_test})
HTML
In your ajax success keep track of which have the values.

Matplotlib into a Django Template

Im using python 3.4 and Django 1.8. I want to "print" a matplotlib result in a Django template. I reach this a few days ago, so I continue in other things of my Django App. Now, I dont know why, I was going to show the result to a friend, and my template with a matplotlib graph, now shows a big code! I dont know why this happen, because my view doesnt change in anything from when it was showing the right graph! Please help me!
This is my view!
from django.shortcuts import render
from matplotlib import pylab
from pylab import *
import PIL
import PIL.Image
import io
from io import *
def graphic(request):
pos = arange(10)+ 2
barh(pos,(1,2,3,4,5,6,7,8,9,10),align = 'center')
yticks(pos,('#hcsm','#ukmedlibs','#ImmunoChat','#HCLDR','#ICTD2015','#hpmglobal','#BRCA','#BCSM','#BTSM','#OTalk'))
xlabel('Popularity')
ylabel('Hashtags')
title('Hashtags')
subplots_adjust(left=0.21)
buffer = io.BytesIO()
canvas = pylab.get_current_fig_manager().canvas
canvas.draw()
graphIMG = PIL.Image.fromstring('RGB', canvas.get_width_height(), canvas.tostring_rgb())
graphIMG.save(buffer, "PNG")
content_type="Image/png"
buffercontent=buffer.getvalue()
graphic = (buffercontent ,content_type)
pylab.close()
return render(request, 'graphic.html',{'graphic':graphic})
Of course in my graphic.html is a variable called {{graphic}} inside a blockcontent!
This was showing the right result in my template! What happen?
Now sometimes when i run my template it shows a big code, or just show me this django error:
Exception Value:
main thread is not in main loop
Exception Location: C:\Python34\lib\site-packages\matplotlib\backends\tkagg.py in blit, line 17
Help!
from io import BytesIO
import base64
import matplotlib.pyplot as plt
import numpy as np
def graphic(request):
pos = np.arange(10)+ 2
fig = plt.figure(figsize=(8, 3))
ax = fig.add_subplot(111)
ax.barh(pos, np.arange(1, 11), align='center')
ax.set_yticks(pos)
ax.set_yticklabels(('#hcsm',
'#ukmedlibs',
'#ImmunoChat',
'#HCLDR',
'#ICTD2015',
'#hpmglobal',
'#BRCA',
'#BCSM',
'#BTSM',
'#OTalk',),
fontsize=15)
ax.set_xticks([])
ax.invert_yaxis()
ax.set_xlabel('Popularity')
ax.set_ylabel('Hashtags')
ax.set_title('Hashtags')
plt.tight_layout()
buffer = BytesIO()
plt.savefig(buffer, format='png')
buffer.seek(0)
image_png = buffer.getvalue()
buffer.close()
graphic = base64.b64encode(image_png)
graphic = graphic.decode('utf-8')
return render(request, 'graphic.html',{'graphic':graphic})
and in the template:
<img src="data:image/png;base64,{{ graphic|safe }}">
I have:
matplotlib==3.0.2 and Django==2.1.4
Edit:
try with
graphic = cStringIO.StringIO()
canvas.print_png(graphic)
return render(request, 'graphic.html',{'graphic':graphic})
You have to specify that your image is a binary string:
<img src="data:image/png;base64,{{graphic|safe}}">
Or actually save it to the filesystem and provide the path.
Alternatively you could use Bokeh which can give you the html + javascript to embed the plot directly in the template, then it is dynamically generated and brings nice features.
The final solution was to create a special view that returns the matplotlib plot in an empty template, like this:
def grafico (rquest):
pos = arange(10)+ 2
barh(pos,(1,2,3,4,5,6,7,8,9,10),align = 'center')
yticks(pos,('#hcsm','#ukmedlibs','#ImmunoChat','#HCLDR','#ICTD2015','#hpmglobal','#BRCA','#BCSM','#BTSM','#OTalk'))
xlabel('Popularidad')
ylabel('Hashtags')
title('Gráfico de Hashtags')
subplots_adjust(left=0.21)
buffer = io.BytesIO()
canvas = pylab.get_current_fig_manager().canvas
canvas.draw()
graphIMG = PIL.Image.fromstring('RGB', canvas.get_width_height(), canvas.tostring_rgb())
graphIMG.save(buffer, "PNG")
pylab.close()
return HttpResponse (buffer.getvalue(), content_type="Image/png")
The next step is to put in your template this:
<img src="url_of_the_graphic_view">
And thats all!
def show(request):
x = np.arange(10)
y = x
fig = plt.figure()
plt.plot(x, y)
canvas = fig.canvas
buf, size = canvas.print_to_buffer()
image = Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1)
buffer=io.BytesIO()
image.save(buffer,'PNG')
graphic = buffer.getvalue()
graphic = base64.b64encode(graphic)
buffer.close()
return render(request, 'graphic.html',{'graphic':graphic})
I had a broken icon image as well, after using the answers above, and I fixed it by removing the b' and ' from the graphic base64 binary representation :
return render(request, 'graphic.html', {'graphic': str(graphic)[2:-1]})

Create a graph from a CSV file and render to browser with Django and the Pandas Python library

I'm learning how to use the Django framework for a work project that will allow users to load files in various formats (at the moment I am only dealing with CSV files), graph that data using Pandas, and display that data back to the user via a Django template. I haven't had any problems creating the graph in iPython, but have been struggling with getting it to an HTML Django template.
I've followed the following example from matplotlib:
# graph input file
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import DateFormatter
def graph(request):
fig = Figure()
ax = fig.add_subplot(111)
x = []
y = []
now = datetime.datetime.now()
delta = datetime.timedelta(days=1)
for i in range(10):
x.append(now)
now += delta
y.append(random.randint(0, 1000))
ax.plot_date(x, y, '-')
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
fig.autofmt_xdate()
canvas = FigureCanvas(fig)
response = HttpResponse( content_type = 'image/png')
canvas.print_png(response)
return response
The above example works great and I can see it in a template, but that's just a graph with hard-coded values.
I've attempted to use Pandas because of its seemingly simplistic syntax and my attempts in Django are as follows:
# graph input file
import pandas as pd
from pandas import DataFrame
def graph(request):
data_df = pd.read_csv("C:/Users/vut46744/Desktop/graphite_project/sampleCSV.csv")
data_df = pd.DataFrame(dataArray)
data_df.plot()
response = HttpResponse( content_type = 'image/png')
return response
In Django calling the .plot() displays the graph fine, but displays a blank page to the HTML template. I've also tried using Numpy's genfromtxt() and loadtxt(), but to no avail. Also, my Google searches have not been fruitful either.
Any help or suggestion would be great. If you know of a better alternative to Pandas then I am willing to try other options.
Haven't tried this yet, but I would attack it something like:
def graph(request):
fig = Figure()
ax = fig.add_subplot(111)
data_df = pd.read_csv("C:/Users/vut46744/Desktop/graphite_project/sampleCSV.csv")
data_df = pd.DataFrame(data_df)
data_df.plot(ax=ax)
canvas = FigureCanvas(fig)
response = HttpResponse(content_type='image/png')
canvas.print_png(response)
return response

Categories

Resources