I would like to ask how to implement Python run time and graphics on website as seen in this Udacity lesson on PD controller?
If run locally, matplotlib will generate a popup window containing the graphics. How is it capture and shown on the website? The text output is shown in the terminal. On Udacity, all of that are shown in a single page. How are they captured and displayed as such? What if you want to display live animation generated by things like turtle graphics?
And how do you provide a code input area with the code presentation as shown to the user? And how do you provide features like LaTex on your page like math.stackexchange.com?
Are there certain frameworks, API and languages you have to use, or is it independent of all that?
You need to use a python backend framework,
I use Django or Flask and run the mathplotlib on my backend and display it in the image formation using the HTML img tag
Here is the example in the flask
app.py
from flask import Flask, render_template
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4, 5])
plt.ylabel('some numbers')
plt.savefig('static/graph.png')
app = Flask(__name__)
#app.route('/')
def home():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
index.html
<!DOCTYPE html>
<html>
<head>
<title>MathPlotLib</title>
</head>
<body>
<div><img alt="Sample Work" src="{{ url_for('static', filename='graph.png') }}">
</div>
</body>
</html>
File System
Main Folder
----templates
----index.html
----static
----graph.png
----app.py
Savefig
So the answer to your question would be instead of plt.show() you do a plt.savefig() as a temporary file in the backend and later add it to the website. There are saving formats like svg that will give you all the benefits of resizing and rendering on the front end side too.
Related
I want to deploy a web map apps which containing several points and Plotly graphs as folium popup. Everything is fine until I want to deploy my web map apps in Flask, which when I click the point, the pop up shows error message says
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
Here is the popup code
#make a dataframe which is used for plotting the well head point in folium
df_point = pd.DataFrame(list(zip(wells, html_list, Longitude, Latitude)), columns =['Well_Name', 'HTML_list', 'Longitude', 'Latitude'])
#Start plotting well head in map with well log plot as a pop up widget
for i in range(0,len(df_point)):
html="""
<iframe src=\"""" + df_point['HTML_list'][i] + """\" width="700" height="800" frameborder="0">
""")
popup = folium.Popup(folium.Html(html, script=True))
# #Cirlce marker ver.
# folium.CircleMarker([df_point['Latitude'].iloc[i],df_point['Longitude'].iloc[i]],
# popup=popup,radius=3.5,opacity=1,color='#ccd132').add_to(map1)
#Marker with icon ver.
folium.Marker([df_point['Latitude'].iloc[i],df_point['Longitude'].iloc[i]],
popup=popup,icon=folium.Icon( icon='glyphicon-pushpin')).add_to(map1)
I put the HTML file, coordinate and name on dataframe which is called df_point, here is the dataframes
Well_Name HTML_list Longitude Latitude
0 Well 1F figWell 1F.html 96.083956 5.456862
1 Well 2F figWell 2F.html 96.356427 5.328133
and here is my Flask app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def render_the_map():
return render_template('testing_map.html')
if __name__ == '__main__':
app.run(debug=True)
and also here is the path if someone need my file path information
How do I put the Plotly graphs in HTML format as pop up folium on Flask? I'm still new in Flask development. Any help I would appreciate it, Thanks!
I found a solution based on Sebastian's answer, if someone want to make a Folium map and the pop up marker showing plotly html in Flask, here's how to do it
first, in the app.py, make a route for the plotly plot
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def render_the_map():
return render_template('testing_map.html')
#app.route('/figure1')
def figure_plotly1():
return render_template('figWell 1F.html')
#app.route('/figure2')
def figure_plotly2():
return render_template('figWell 2F.html')
if __name__ == '__main__':
app.run(debug=True)
and then, search your plotly code in your folium map html and change the iframe source to the defined route, so for example, my plotly html graph name is figWell 1F.html, try to ctrl+F in your main HTML folium map and change the iframe src to be like this
<iframe src="{{url_for('figure_plotly1')}}" width="700" height="800"
and it works like a charm
Currently I am using flask and heroku to deploy my website but i need my webpage show random photo from img directory currently my code look like this
import os
import random
imgs = os.listdir('static/img')
imgs = ['img/' + file for file in imgs]
imgrand = random.sample(imgs,k=5)
#app.route('/')
def index():
return render_template('index.html', imgrand=imgrand)
And my HTML code look like this
{% for img in imgrand %}
<img src="static/{{img}}" alt="{{imgL}}" style="width:100%">
{% endfor %}
So long it work fine in my local machine ,but it only random picture only once when start flask run command in terminal. My goal is to make my web page random picture everytime when refresh webpage without going to end terminal session and start flask run command all over again.
In this case imggrand variable only takes one sample at the beggining of the program, for repeating the process everytime you refresh the webpage you need to put imggrand inside the endpoint.
I recommend you to learn about endpoints and designing the workflow starting with this: https://flask.palletsprojects.com/en/1.1.x/quickstart/#rendering-templates
I am trying to set up a side project on DigitalOcean, and I am using the git framework from https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xvii-deployment-on-linux to get started.
Within this framework, I have added code within one of the flask routes (/explore) in which I generate a plot with matplotlib, and I want to return this plot as an object when I render the template as the return function of this route. I don't need to save the plot if it can be sent to the template without doing so (e.g with io.BytesIO()), but I have been unable to get the syntax correct to use this approach and get the plot to render in the resulting template.
While my attempts with io.BytesIO() have been unsuccessful, if it would help to output the results with that approach, please let me know how to best utilize it, and I will attempt to run this code with the suggested changes and report the results.
Thank you in advance!
I have tried to save the file and send it to the template, as well as sending the file data via BytesIO(), but neither approach has worked for me.
Below is my attempt to save the file to the static directory and send the image to the template, but a solution that works in this environment with io.BytesIO() or similar without saving the file would be even better.
Here is the code that I added to the explore route in /app/main/routes.py to save the plot image to the static directory and return the path to the template:
new_graph_name = url_for('static', filename='tmp_png.png')
plt.savefig(new_graph_name)
return render_template('index.html', url=new_graph_name)
Here is the code that I added to the index.html template:
{% if url %}
<img src={{ url }} alt="Chart" height="42" width="42" />
{% endif %}
In terms of saving the plot and then displaying it, could you try something similar to the code the below? This has worked for me recently.
In routes.py:
#app.route("/")
def index():
new_graph_name = 'tmp_png'
plt.savefig('static/images/' + new_graph_name)
return render_template("index.html", new_graph_name=new_graph_name)
In index.html:
<img src="{{ url_for('static', filename='images/' + new_graph_name + '.png') }}"
With Bytes.IO I think I've tried something like this before:
In routes.py:
import io
from io import BytesIO
import base64
img = io.BytesIO()
fig.savefig(img)
img.seek(0)
buffer = b''.join(img)
b2 = base64.b64encode(buffer)
barplot=b2.decode('utf-8')
I cannot remember how I displayed it in the .html template but could it just be a matter of passing it as a variable?
For seemingly no reason my angular $scope variable is not rendering in the browser. My whole project has been working just fine until I created this page today. All other pages still work as expected. I've deleted all my code down to just the variable itself with the following code and its still rendering as [undefined].
I'm using python/flask to serve up the application with the jinja templating engine and therefore have changed the interpolation characters for angular so they don't conflict with the same characters in jinja:
var zues = angular.module('zues', []);
zues.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('{{[');
$interpolateProvider.endSymbol(']}}');
}]);
Controller:
zues.controller('test', ['$scope', '$http', function($scope, $http){
$scope.test123 = "testing123";
}]);
HTML:
<body ng-app="zues" ng-controller="test">
{{[ test123 ]}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="/static/assets/js/zues.js"></script>
<script src="/static/assets/js/Controllers/test.js"></script>
python/flask route:
from flask import Flask, render_template
import flask
application = Flask(__name__)
#application.route("/test")
def test():
return render_template('test.html')
if __name__ == "__main__":
application.run(host='127.0.0.1', reloader_type='stat', debug=True)
This renders in the browser simply as:
[Undefined]
I would have expected it to render:
testing123
Anything simple that I'm just overlooking?
I figured it out. My interpolation characters that I picked for angular were too closely related to the characters that Jinja uses by default. Jinja was taking {{[ test123 ]}} and interpreting the square brackets as plain text and then trying to find a variable test123 within my python script that didn't exist.
This didn't seem to break on the rest of the project because the angular variables I used in my html templates in the rest of the project were always bound to something else and therefore being watched by the digest loop whereas in this scenario it would only have been interpolated once.
I changed the interpolation characters to be {[{ test123 }]} so that Jinja never catches it and only angular does.
A few quick changes should help.
1) Get rid of the interpolate provider. You won't need this code if you complete 2 & 3 below.
2) Remove the close bracket ] when you close the controller definition
Yours: }]);
Mine: });
3) Add {{ ' before the set of curly braces and after ' }}
example/ {{ '{{someVariable + "" + anotherVariable}}' }}
I'm very new to Python. I just know what Python is.
I have created the below code (in Python IDLE):
print "Hi Welcome to Python test page\n";
print "Now it will show a calculation";
print "30+2=";
print 30+2;
Then I saved this page in my localhost as index.py
I run the script using
http://localhost/index.py
But it does not show the executed Python script. Instead, it showed the above code as HTML. Where is the problem? How can I run a Python file in a web page?
In order for your code to show, you need several things:
Firstly, there needs to be a server that handles HTTP requests. At the moment you are just opening a file with Firefox on your local hard drive. A server like Apache or something similar is required.
Secondly, presuming that you now have a server that serves the files, you will also need something that interprets the code as Python code for the server. For Python users the go to solution is nowadays mod_wsgi. But for simpler cases you could stick with CGI (more info here), but if you want to produce web pages easily, you should go with a existing Python web framework like Django.
Setting this up can be quite the hassle, so be prepared.
As others have pointed out, there are many web frameworks for Python.
But, seeing as you are just getting started with Python, a simple CGI script might be more appropriate:
Rename your script to index.cgi. You also need to execute chmod +x index.cgi to give it execution privileges.
Add these 2 lines in the beginning of the file:
#!/usr/bin/python
print('Content-type: text/html\r\n\r')
After this the Python code should run just like in terminal, except the output goes to the browser. When you get that working, you can use the cgi module to get data back from the browser.
Note: this assumes that your webserver is running Linux. For Windows, #!/Python26/python might work instead.
Using the Flask library in Python, you can achieve that.
Remember to store your HTML page to a folder named "templates" inside where you are running your Python script.
So your folder would look like
templates (folder which would contain your HTML file)
your Python script
This is a small example of your Python script. This simply checks for plagiarism.
from flask import Flask
from flask import request
from flask import render_template
import stringComparison
app = Flask(__name__)
#app.route('/')
def my_form():
return render_template("my-form.html") # This should be the name of your HTML file
#app.route('/', methods=['POST'])
def my_form_post():
text1 = request.form['text1']
text2 = request.form['text2']
plagiarismPercent = stringComparison.extremelySimplePlagiarismChecker(text1,text2)
if plagiarismPercent > 50 :
return "<h1>Plagiarism Detected !</h1>"
else :
return "<h1>No Plagiarism Detected !</h1>"
if __name__ == '__main__':
app.run()
This a small template of HTML file that is used:
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Enter the texts to be compared</h1>
<form action="." method="POST">
<input type="text" name="text1">
<input type="text" name="text2">
<input type="submit" name="my-form" value="Check !">
</form>
</body>
</html>
This is a small little way through which you can achieve a simple task of comparing two strings and which can be easily changed to suit your requirements.
If you are using your own computer, install a software called XAMPP (or WAMP either works). This is basically a website server that only runs on your computer. Then, once it is installed, go to the xampp folder and double click the htdocs folder. Now you
need to create an HTML file (I'm going to call it runpython.html). (Remember to move the Python file to htdocs as well.)
Add in this to your HTML body (and inputs as necessary).
<form action = "file_name.py" method = "POST">
<input type = "submit" value = "Run the Program!!!">
</form>
Now, in the Python file, we are basically going to be printing out HTML code.
# We will need a comment here depending on your server. It is basically telling the server where your python.exe is in order to interpret the language. The server is too lazy to do it itself.
import cgitb
import cgi
cgitb.enable() # This will show any errors on your webpage
inputs = cgi.FieldStorage() # REMEMBER: We do not have inputs, simply a button to run the program. In order to get inputs, give each one a name and call it by inputs['insert_name']
print "Content-type: text/html" # We are using HTML, so we need to tell the server
print # Just do it because it is in the tutorial :P
print "<title> MyPythonWebpage </title>"
print "Whatever you would like to print goes here, preferably in between tags to make it look nice"
Well, the OP didn't say server or client side, so I will just leave this here in case someone like me is looking for client side:
Skulpt is a implementation of Python to run at client side. Very interesting, no plugin required, just simple JavaScript code.
With your current requirement, this would work:
def start_html():
return '<html>'
def end_html():
return '</html>'
def print_html(text):
text = str(text)
text = text.replace('\n', '<br>')
return '<p>' + str(text) + '</p>'
if __name__ == '__main__':
webpage_data = start_html()
webpage_data += print_html("Hi Welcome to Python test page\n")
webpage_data += fd.write(print_html("Now it will show a calculation"))
webpage_data += print_html("30+2=")
webpage_data += print_html(30+2)
webpage_data += end_html()
with open('index.html', 'w') as fd: fd.write(webpage_data)
Open the index.html file, and you will see what you want.