Replacing text from string with an image using flask - python

I have written a piece of code that matches if the string has anything of the pattern text.someExtension, In my case, it would be fileName.png in the string, converts it into an img tag and displays on the HTML file using python and flask. Let us take the example string:
"What is the output of this program? e.png"
the code matches e.png and it then replaces e.png by
"<br><img src="{{url_for('static', filename='pics/e.png')}}" /><br>"
The image e.png is put in the folder pics inside the static folder.
If this string is pushed into a flask variable even by adding Markup() to it it isn't rendering the image but showing the following output.
output on html page
why is it so? Any way to make it display the image e.png?
my code is:
import re
from flask import Flask, Markup, render_template
app = Flask(__name__)
def rep(x):
text = re.findall(r'\w+[.]\w+', x)
for i in text:
b ="<img src=\"{{ url_for('static',filename='pics/"+i+"')}}\">"
x=x.replace(i,b)
return x
#app.route('/')
def home():
a = "What is the output of this program? e.png"
a = rep(a)
return render_template('new.html',var=Markup(a))
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=8032)
And the HTML file is,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{var}}
</body>
</html>

The problem is that the value you're passing to your template is a string and even though the string you're inserting is formatted with the {{ brackets, flask doesn't interpret those. Notice if you look at the html being served, it actually contains the string 'url_for'...
You're also not even importing the url_for function from flask, so that wouldn't have worked anyway.
The solution:
import re
from flask import Flask, url_for, Markup, render_template
app = Flask(__name__)
def rep(x):
text = re.findall(r'\w+[.]\w+', x)
for i in text:
b ="<img src='" + url_for('static', filename='pics/'+i) + "'>"
x=x.replace(i,b)
return x
#app.route('/')
def home():
a = "What is the output of this program? e.png"
a = rep(a)
return render_template('new.html', var=Markup(a))
#app.route('/static/<path:path>')
def static_file(path):
return send_from_directory('static', path)
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=8032)
The html file can remain unchanged. This solution
separately tells the flask server to listen and serve the static files under the /static page.
Creates the html with the image url by string concatenation, instead of trying to use template rendering.

Related

Linebreak of a yaml not displaying at an html file

I am having a ymal file and a html file where some of the content in the ymal file is loaded into the html file (see below). I would like to add linebreaks to the string in the ymal file such that it is shown in separate lines when the html file is loaded. I am using flask and jupyter to load the html file.
The html file is loaded correctly but whatever i try it seems that I cannot get the string to break where I want it to.
Does anyone can help me to add linebreaks in the yaml files such that they are shown in the html file?
Thank you.
python code:
import oyaml as yaml
from flask import Flask
from flask import render_template
app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False
#app.route('/')
def index():
website_data = yaml.load(open('_config.yaml'))
return render_template('home.html', data=website_data)
if __name__ == '__main__':
app.run()
My yaml code:
profile:
first_name: |
I would like to have a break here.\n
And then I would also to have a break here\\
But it does not work whatever I try</br>.
My html code:
<!DOCTYPE html>
<html>
<body>
<h1>My homepage</h1>
<p>{{ data.profile.first_name }} </p>
<p>This is a test website again</p>
</body>
</html>

Flask doubles contents of page when refreshing

I have a simple Flask script which loads a Pandas-file (created in another .py-file) and displays this.
It shows everything, I want... But as soon as I refresh the page,the same content is added!
here is the Flask-thing:
from flask import Flask,render_template
import Python_script
import pandas as pd
app = Flask(__name__)
#app.route("/")
def home():
a = Python_script.summary()
df=pd.DataFrame(a)
return render_template('simple.html', tables=[df.to_html(classes='overview')], header='true')
if __name__ == "__main__":
app.run(debug=True)
Python_script.summary returns a list
and here's the html-code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
</head>
<body>
{% for table in tables %}
{{ table|safe }}
{% endfor %}
</body>
</html>
what needs to be done so when you refresh, it doesn't add but it simply updates the page?
Many thanks,
Peter
If I understood correctly from your comment, your Python_script looks like:
e = []
def summary():
a = 2
e.append(a)
return e
If that is the case, then you have a problem. e is a global variable, so any time you call summary() method it will add more values to it. The Flask code looks fine. You need to change your logic for summary in order not to have data extended.
As per your comment, if this is the content of Python_script.py:
e=[]
def summary():
a = 2
e.append(a)
return e
Then you add a debug line to the Flask route:
import Python_script
#app.route("/")
def home():
a = Python_script.summary()
print(Python_script.e)
# ...
You will see that Python_script.e is a global variable and 2 is appended to that list on subsequent requests.
A quick fix may be to make a global within the Flask app, by moving the line which assigns it.
import Python_script
a = Python_script.summary()
#app.route("/")
def home():
print(Python_script.e)
# ...
Now subsequent requests do not append 2 to the list. By doing this a is assigned when the server process starts, rather than when the request is handled, because that line was moved out of the Flask route, and to the global level.
If you're trying to implement a way to maintain this list in real-time, then global variables are not the way to go, this is the job of another storage backend.

Flask redirect stops working after one try?

When I run flask with python test.py, and then navigate to http://localhost:5000 in my browser, I would expect the terminal to read:
test-1 test-2 test-3
The three print statements ONLY appear when test.py is run for the first time. After that, the terminal will only show:
test-1 test-2
For some reason, the redirecting to the second page is not occurring after the initial run. Is there some sort of weird caching nonsense going on? Can someone please explain what is happening?
from flask import Flask, redirect, url_for, send_from_directory
app = Flask(__name__)
#app.route('/')
def home():
print('test-2')
return redirect(url_for('page2'))
#app.route('/secondPage')
def page2():
print('test-3')
return send_from_directory('.', 'test_dashboard_4.html')
if __name__ == '__main__':
print('test-1')
app.run(debug=True)
I was finding lying around and I found this question is old and no answers yet.
So I will be the one who may help you.
Use render_template and put all of your htmls to templates folder. Something like this
import flask
app = flask.Flask("My life sucks")
#app.route('/')
def index():
return flask.render_templates('your html page here.')
if __name__ == '__main__':
app.run(debug=True)
One other thing, you can't put javascript to same directory where html was.
Instead put it in static folder and add static to where you import javascript like.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body>
<h1>
Hello world!
</h1>
<script src="static/hi.js"></script>
</body>
</html>
This is javascript file if you want to see something
console.log("I get imported!");
document.body.innerHTML += '<p>:D</p>'
Here's the tree
D:.
│ app.py
│
├───static
│ hi.js
│
└───templates
index.html

Python Flask to change text in a HTML file

I'm trying to create a simple program which will replace {{ test }} with 'Hello world' by following a tutorial, however I am stumped and when I open the HTML file - as {{ test }} is shown on the page instead of 'Hello World' which is what should be appearing.
Any help would be appreciated because I am very unsure on what to do to fix this, thanks.
I am unsure if I have even linked the two files, as to my knowledge it was never specified in the video and I have only just noticed that there is no link between the two files.
Python Code:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def homepage():
return render_template('index.html', test='hello world')
if __name__ == '__main__':
homepage()
else:
print('Please run this file as main, not as module.')
HTML Code:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<p> {{ test }} </p>
</body>
</html>
Flask is a webserver. You are not meant to call the functions with app.route. Replace the last part with:
if __name__ == '__main__':
app.run()
and then visit http://127.0.0.1:5000/ in your browser. The template file is not meant to change.
If for some reason you don't want to run a server but you just want to create HTML files, then use Jinja2, the template engine behind Flask.

Difficulty accessing json file with d3 and flask

I am using Flask as a web framework, and I am trying to implement the first example from the book Getting Started with D3, by Mike Dewar. I have a Python script named run.py and two directories, templates/ and static/, containing index.html and service_status.json, respectively. Unfortunately, my code is not rendering the data at all, nor is it producing any glaring errors.
This is what I have in run.py:
#!/usr/bin/env python
from flask import Flask, render_template, url_for
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
if __name__=="__main__":
port = 5000
app.debug = True
app.run( port=port )
This is what I have in templates/index.html:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<META CHARSET="utf-8">
<SCRIPT SRC="http://d3js.org/d3.v3.min.js"></SCRIPT>
<SCRIPT>
function draw(data) {
"use strict";
d3.select("body")
.append("ul")
.selectAll("li")
.data(data)
.enter()
.append("li")
.text( function(d){
return d.name + ": " + d.status;
}
);
}
</SCRIPT>
<TITLE>MTA Data</TITLE>
</HEAD>
<BODY>
<H1>MTA Availability Data</H1>
<SCRIPT>
d3.json("{{ url_for( 'static', filename='service_status.json') }}",draw); // <---- BIG PROBLEM
</SCRIPT>
</BODY>
</HTML>
I am using Windows 7, Google Chrome, and Python 2.7.
If the JSON file is not going to change, then you should put it in the static directory and use
from flask import url_for
url_for('static', filename='service_status.json')
For this to work, also change the path in the JavaScript to '/static/service_status.json'
Static files like your json document, are by default served from a different directory from the templates - by default 'static'
You dont need to use the url_for call in your view, you can use it in your template:
d3.json("{{ url_for('static', filename='service_status.json') }}",draw);
So to summarise: 1) Move your json document in to the static folder (a folder called static along side your templates folder, by default), and 2) use the url_for call in your template to get the correct URI for your json document.
If you want to use a folder other than static, you can change that by passing static_folder to the Flask object contructor
You seem to be getting a 304 status code as you mentioned in earlier comments. I see that your JSON has the following date/time:
"Date": [
"12/15/2011"
],
"Time": [
" 7:35AM"
],
I am not 100% sure but this might help:
http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#if-modified-since
Basically, it says that
"This request header is used with GET method to make it conditional: if the requested document has not changed since the time specified in this field the document will not be sent, but instead a Not Modified 304 reply.
Format of this field is the same as for Date:"
So, may be you can check the timestamp on the JSON and probably just do a fresh save ?

Categories