Flask serves static file, but without images - python

I am trying to serve static files from Flask, but said static file contains an image which is not showing up. Here is my flask code:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return app.send_static_file("somefile.html")
if __name__ == '__main__':
app.run(debug = True)
And here is my html file "somefile.html" which is in the "static" sub-directory under the directory which holds the above code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div> this is some garbage text </div>
<img id="ansvg" src="./ppnow.svg">
</body>
</html>
The graphic is sitting in the same "static" subdirectory as somefile.html.
If I drag the html file directly into the browser, no problem, I get the graphic, but if I run the flask server and point to localhost:5000 then the graphics doesn't show up (though the text does).
What's going on? Thank you.

You are serving the HTML page under the root URL, /. The browser will then load all relative URLs based of the root url.
Your image is thus going to be loaded as /ppnow.svg, not /static/ppnow.sgv.
You could fix the link to the image, or you could alter the base URL with a <base> tag:
<base href="/static/">
Note that without a domain name (an absolute URL) the base tag may be ignored by IE.

Related

Flask url_for() ERROR: in url_for "Attempted to generate a URL without the application context being" [duplicate]

I have a trivial app where I'm trying to redirect the favicon per:
http://flask.pocoo.org/docs/0.10/patterns/favicon/
app = flask.Flask(__name__)
app.add_url_rule('/favicon.ico', redirect_to=flask.url_for('static', filename='favicon.ico'))
But this fails with:
RuntimeError: Attempted to generate a URL without the application context being pushed. This has to be executed when application context is available.
So, guessing, I try this:
app = flask.Flask(__name__)
with app.app_context():
flask.current_app.add_url_rule('/favicon.ico', redirect_to=flask.url_for('static', filename='favicon.ico'))
But get a different error:
RuntimeError: Application was not able to create a URL adapter for request independent URL generation. You might be able to fix this by setting the SERVER_NAME config variable.
What is going on?
According to the doc:
Setting a SERVER_NAME also by default enables URL generation without a request context but with an application context.
since you're using app_context, you may set the SERVER_NAME Configuration Value.
By the way, as the doc:Adding a favicon says:
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
the above line should be enough for most browsers, we don't have to do any other things.
Late answer, I've just run into the same problem. I don't see a big downside in handling the redirect like this instead:
#app.route('/favicon.ico')
def favicon():
return redirect(url_for('static', filename='favicon.ico'))
This prevents url_for from being called before the application is ready.
To give a counterpoint to using a link in the HTML only, it's a good practice for every site to have a favicon.ico and robots.txt at the root level - even if they're empty. It avoids problems like this and other unnecessary errors that adds noise to logs.
Don't put this in the app but in the html file
<html lang="en">
<head>
<title>{{ title }}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width/2, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

Why images can be shown only if they are in `static` folder?

I'm building a image recognition Flask project. And I want the image shown on the web page. Here is the structure of my project:
As you can see, static,templates and upload are in the same folder. If I save the image into static folder (which is generated by the VS2015 flask project) and write the result.html like this:
<!doctype html>
<h3>{{ outcome_info }}</h3>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<title>Flood Classifier</title>
</head>
<body>
<img src="{{url_for('static', filename=thename)}}">
</body>
</html>
The image would shown successfully when this Python function is called:
#app.route('/classify', methods=['POST','GET'])
def classify():
global image
image = np.expand_dims(image, axis = 0)
result = model.predict(image)
if result[0][0] == 1:
result = "flood"
else:
result = "no flood"
return render_template('result.html', thename = imagename, outcome_info = result)
However, if I save the image file into upload (which is created by myself), and just change the folder name in result.html like this:
<!doctype html>
<h3>{{ outcome_info }}</h3>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<title>Flood Classifier</title>
</head>
<body>
<img src="{{url_for('upload', filename=thename)}}">
</body>
</html>
The image would not shown when call that Python function. Do the images must be saved into static folder or there is something that I misunderstand?
you can use this configuration:
from flask import Flask
app = Flask(__name__, static_url_path = "/upload", static_folder = "upload")
Then you can access your images as follows:
<img src='/upload/image1.jpg' width="200" height="85">
check this answer for more details: Cannot show image from STATIC_FOLDER in Flask template
I think you misunderstand how url_for works.
The first parameter is endpoint, endpoint is roughly a registered route handler. And static is a built-in route handler which handles all requests to http://yourserver/static/xxxx.
When you set static_folder, you set the flask to serve all files under that folder through route static. You can also override this default route by setting static_url_path.
doc

Write HTML received as string to browser

I have a basic HTML file which looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
I am receiving the file in python and storing it as a string. I want to know, is there a way I can write this out to a web browser?
The file is on my computer, so my goal is not to save it as an html file and then execute it, but rather execute this from within python to the browser.
I know that with JavaScript I can use Document.write() to inject content to a webpage, but that is already being done in the browser. I want to achieve something similar.
You can use flask, a simple Python web framework, to serve the string:
Using flask (pip install flask):
import flask
app = flask.Flask(__name__)
s = """
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
"""
#app.route('/')
def home():
return s
if __name__ == '__main__':
app.debug = True
app.run()
Now, can you navigate to 127:0.0.1:5000 or the equivalent IP and port specified when the app is run.
You could do the following:
html = """<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>"""
with open('html_file.html', 'w') as f:
f.write(html)
import webbrowser, os
webbrowser.open('file://' + os.path.realpath('html_file.html'))

Flask : href link to html not working

I have a basic Flask app with the following structure :
from flask import Flask
from flask import render_template
app = Flask(__name__,template_folder='E:\Programming\Python Projects\Flask')
#app.route('/')
def index():
return render_template('hello.html')
#app.route('/route/')
def route1():
return render_template('route1.html')
app.run(debug = True,port = 8080,host = '0.0.0.0')
hello.html :
<!DOCTYPE html>
<html>
<head>
<title>Rendered!!</title>
</head>
<body>
<h1>
The template has been rendered!!!<br>
Route No. 1
</h1>
</body>
</html>
route1.html :
<!DOCTYPE html>
<html>
<head>
<title>Route No. 1</title>
</head>
<body>
<h2>
This is the first route!!!<br>
Hello World!!!
</h2>
<iframe src="https://www.youtube.com/embed/YQHsXMglC9A" width="853" height="480" frameborder="0" allowfullscreen></iframe>
</body>
</html>
When I open localhost:8080 it works fine.
But when I click on the link, it says :
The address wasn’t understood
Firefox doesn’t know how to open this address, because one of the following protocols (localhost) isn’t associated with any program or is not allowed in this context.
It works fine when I type the address localhost:8080/route manually in the address bar.
Also, it works fine when opened in a new tab.
I need help!!!
Thank You !!!
You should use from flask import render_template, url_for
and in the template:
<h1>
The template has been rendered!!!<br>
Route No. 1
</h1>
Just let Flask and Jinja2 make the URL's for you...
*It seems that you forgot the trailing slash at the link.
Should be localhost:8080/route/
But its far better to use url_for as it avoids this type of problem

serving an image with python and flask not working [duplicate]

This question already has answers here:
Link to Flask static files with url_for
(2 answers)
Closed 6 years ago.
I reduced the code for this to, I think, minimum while trying to get it to work:
The python:
#!/usr/bin/env python
from functools import wraps
from flask import Flask, render_template, session, request, redirect, url_for
from flask_socketio import SocketIO, emit, join_room, leave_room, \
close_room, rooms, disconnect
async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)
#app.route('/')
def index():
return render_template('index_test.html')
if __name__ == '__main__':
socketio.run(app, debug=True)
The html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="{{ url_for('index') }}bulboff.gif"/>
<p>"{{ url_for('index') }}" <p>
</body>
</html>
The image is in the static folder.
And it gives this error:
"GET /bulboff.gif HTTP/1.1" 404
when the page is accessed.
I've tried several things like setting the Flask default paths, without the url_for, etc, but, still no image.
What am I missing?
According to the flask document:
To generate URLs for static files, use the special static endpoint
name:
url_for('static', filename='style.css')
The file has to be stored on the filesystem as static/style.css.
In your case, use <img src="{{ url_for('static', filename='bulboff.gif') }}">
If You put image in the static folder, You should use something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="{{ url_for('index') }}static/bulboff.gif"/>
<p>"{{ url_for('index') }}" <p>
</body>
</html>
Alternatively, You could change application's code and add following:
#app.route('/bulboff.gif')
def bulboff():
return open('static/bulboff.gif').read()
<img src="{{url_for('static', filename='bulboff.gif')}}" />
Try that. Your filename could be a path from the static folder. So like if you have filename = \some\path\img.png it will look for the img in static\some\ath\img

Categories