I'm trying to run a Python script with HTML code embedded and it's not working. I'm want to execute a Python script and at the same time render the HTML which will be printed by the script.
app.py:
#!/usr/bin/python2.6
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/briefing')
def briefing():
return render_template('briefing.html')
#app.route('/briefing/code')
def app_code():
return render_template('app_code.py')
if __name__ == '__main__':
app.run(debug=True)
app_code.py:
http://i.stack.imgur.com/sIFFJ.png
When I access http://127.0.0.1:5000/briefing/code the result is http://i.stack.imgur.com/iEKv2.png.
I know that what is happening is that I'm rendering as HTML and therefore the Python code inside of the file is not being interpreted.
How can I run the app_code.py and at the same time, render the HTML from it?
You are mixing up a lot of things, I saw the first post of the question took me a while to figure out what you are trying to do.
The idea that you seem to need to grasp is that, you'll need to prepare the model in Python first (e.g. a string, an object, a dict etc with the data you want), and then inject it into a template to be rendered (as opposed to printing out what you want to see in the HTML output)
If you want to display the output from a subprocess.call into an HTML page, here's what you should do:
Get the output from subprocess in a string format
Create a HTML template to display it in
Make Flask call the subprocess, render the template and return the HTTP response
app.py:
#!/usr/bin/python2.6
import subprocess
from flask import Flask, render_template
app = Flask(__name__)
def get_data():
"""
Return a string that is the output from subprocess
"""
# There is a link above on how to do this, but here's my attempt
# I think this will work for your Python 2.6
p = subprocess.Popen(["tree", "/your/path"], stdout=subprocess.PIPE)
out, err = p.communicate()
return out
#app.route('/')
def index():
return render_template('subprocess.html', subprocess_output=get_data())
if __name__ == '__main__':
app.run(debug=True)
subprocess.html:
<html>
<head>
<title>Subprocess result</title>
</head>
<body>
<h1>Subprocess Result</h1>
{{ subprocess_output }}
</body>
</html>
In the above template, {{ subprocess_output }} will be replaced by the value you pass from your Flask view before the resulting HTML page is sent to the browser.
How to pass more than one value
You can either render_template('page.html', value_1='something 1', value_2='something 2')
and in the template: {{ value_1 }} and {{ value_2}}
Or you can pass a dict called e.g. result:
render_template('page.html, result={'value_1': 'something 1', 'value_2': 'something 2'})
and in the template {{ result.value_1 }} and {{ result.value_2 }}
Related
I have a trained model for speech synthesis. It creates audio correctly everytime from textarea in html page and saves it static folder. But sometimes when i return audio from folder it brings the older one. It doesnt happen everytime but i couldnt find solution.
html audio code
{% if my_audio %}
<audio controls>
<source src="{{ url_for('static', filename='a.wav') }}" type="audio/wav"/>
</audio>
{% endif %}
flask code if you needed
from flask import Flask, render_template, request
import inference
app = Flask(__name__)
app.static_folder = 'static'
#app.route("/")
def home():
return render_template("index.html")
#app.route("/sentez", methods = ["POST"])
def sentez():
if request.method == "POST":
metin = request.form["metin"]
created_audio = inference.create_model(metin)
return render_template("index.html", my_audio = created_audio)
if __name__ == "__main__":
app.run();
This issue arises due to the browser fetching the file from its cache instead of the static folder, after the first run. You need to append a parameter to to the audio file's URL (or query string) that would be unique, so that it will fetch a new copy from the static folder. I suggest appending number of milliseconds elapsed, getTime() method does this in JavaScript.
The JavaScript equivalent for changing the source is as follows:
function playAudio() {
var audioFile = new Audio('./a.wav');
//URL is ./a.wav
audioFile.play()
}
change this to
function playAudio() {
var audioFile = new Audio('./a.wav?' + new Date().getTime());
//URL becomes something like ./a.wav?1623483193060
audioFile.play()
}
You can find out how to do the same in Flask for modifying the statement
{{ url_for('static', filename='a.wav') }}
I use flask to make web server.
in html,
<body>
{{ url_for('test1') }}
</body>
in python,
def test2():
str = "sample!"
yield str
#app.route("/test1")
def test1():
return Response(test2())
I wanna show this on html page as string
but the result is '/test1'
what should I do?
Not render_template please..
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?
Getting this error <generator object inner at 0x7f2ad7874050> on my page when I try to run the folliwhing flask function (route):
#app.route('/siteON', methods=['GET', 'POST'])
def siteon():
def inner():
proc = subprocess.Popen(
['/root/site_toggle/flaskr/testON.sh'],
shell=True,
stdout=subprocess.PIPE
)
for line in iter(proc.stdout.readline,''):
time.sleep(1)
yield line.rstrip() + '<br/>\n'
output = inner ()
return render_template('layout.html', ON_output=output)
here is my html
<input type="button" name="lien2" value="Turn OFF site"
onclick="self.location.href='http://10.10.10.30:5000/siteOFF'" style="background-color:#1ab171"
style="color:white; font-weight:bold"onclick>
<p>{{ ON_output }}</p>
I am looking to run button and display the output on the same flask page without streaming the output on a new page.
Thanks in advance for your help
That's not an error, that's the string representation of a generator object, which is what yield results in your function creating.
You seem to be trying to use a generator and sleep() to make things appear over time in your page, but that's not how templates work - they're a one-and-done kind of rendering. If you want things to appear over time in your page you're probably going to have to use some form of client-side javascript to fetch new updates.
I'm having issues with my flask code, it won't simply return the same structure I want it to
Here's my code for starters:
from flask import Flask, render_template, jsonify, request
from lxml import html
import urlopen, urllib
import requests
from bs4 import BeautifulSoup
import time
import datetime
app = Flask(__name__)
#app.route("/")
def index():
#tv
tvPage = requests.get("https://www.freeview.co.uk")
tvSoup = BeautifulSoup(tvPage.content)
tvData = tvSoup.find_all("div",{"class": "box__listing"})
tvList = []
for program in tvData:
tvList = tvList + [program]
tvNews = tvList
return render_template("main.html", tvNews=tvNews)
if __name__ == '__main__':
app.run(debug=True,port=6500)
And in the html template I got the following:
{% for program in tvNews %}
<li>{{ program.text }}</li>
{% endfor %}
This returns the following: http://imgur.com/a/Va0AH
My question is: How can I make it so each new timeslot is on a new row? Right now it treats the 9pm and 10pm as one string, and not the way Freeview displays it (see screenshot)
When I run it in terminal I get it in new rows, and when I inspect the element with chrome dev tools, it looks like they are on all new rows. What am I doing wrong?
Thanks a lot.
Add safe filter to your variable:
{{ program.text|safe }}