I'm trying to display images located in a folder which is not the default static folder.
My template looks like:
{% extends "layout.html" %}
{% block body %}
Albums
{% for album in albums %}
<img src="{{ album ['ThumbPath'] }}">
{% endfor %}
{% endblock %}
The generated HTML looks like:
<!doctype html>
<title>iPhoto</title>
<link rel=stylesheet type=text/css href="/static/style.css">
<div class=page>
<h1>iPhoto</h1>
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-180444/t264vvMaQM+GJosBP+4q+Q/_DSC1225.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181030/urU3jqSKRgGNNP1MjKhpvg/_DSC1268.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181037/1zYyNYReRg+Sizx8v4BUkw/_DSC0923.jpg">
<img src="/Users/Darrell/Pictures/iPhoto Library/Thumbnails/2013/08/09/20130809-181038/sKzEEB3jSf6GBs2heQIviA/Kelly.jpg">
</div>
How can get the images to be rendered on the generated webpage.
The path to the image is correct.
It is no option to copy all images to the static folder.
Darrell
Look like you have file system path instead site. When you start resource with / then path will start from site root (absolute path for site, without slash or with ./ or ../ is relative) for example if you have site http://test.com then / will be http://test.com/ or /test will be http://test.com/test. You can set path with specific protocol protocol:// or identical for current site // for another sites. You always can found errors with wrong (full) urls in your browser error console.
To get access to file system you must use file:// protocol and you urls will be like file:///Users/Darrell/Pictures/.... But it will work only for your computer and can have security issues. You also can set symbolic link for this files to static folder and this resolve security issues, but not resolve issue with only your computer. To completely resolve this issue better publish this files to your application or on public (private) web servers for images or another static.
So here is my project path. I wrote a simple function that would work by allowing it to render on the webpage. I am not a 100% sure if it would work once deployed, so I will update if it does work when deployed.
<img alt="" src="{{ url_for('send_file', filename=image_url) }}" id ="img"/>
This is the code of the HTML element and here is its corresponding code in Python on the server side.
def getImageName(x):
"""
Dealing with Unix Path names and Windows PathNames
"""
if platform.system() == 'Linux':
return x[x.rfind("/")+1:]
return x[x.rfind("\\")+1: ]
def getFolder(x):
y = []
if platform.system() == 'Linux':
y = x.split("/")
else:
y = x.split("\\")
# print(y)
cat_name = ""
if "roomImage" in x:
cat_name+="roomImage/" + y[-2]
elif "lobbyImage" in x:
cat_name+="lobbyImage"
elif "miscImage" in x:
cat_name += "miscImage/" + y[-2]
elif "washroomImage" in x:
cat_name += "washroomImage"
else:
cat_name += "facadeImage"
return cat_name + "/"
#app.route("/send_file/<filename>")
def send_file(filename):
return send_from_directory(app.config["UPLOAD_FOLDER"] +"/" + getFolder(filename) , getImageName(filename))
This works for the most part.
By the way, image_url is supposed to the be the absolute path of the image that you can pass as an argument to the Jinja2 template via render_template like so:
return render_template("/contentpage.html",image_url=imgurl)
Don't forget to import send_from_directory and set app.config["UPLOAD_FOLDER"] to the appropriate directory. This isn't the most efficient way to do it
Related
I am old timer but young learner. I want make my own website, using Python and Bottle.
I have an HTML page which contains a title, a subtitle and a photo. This is a template used by Bottle in this little code:
from bottle import route, run, view
#route("/")
#view("pagedegarde.html")
def menu() :
contenu = "Moto de l'abbé Khan"
return {"titre" : "Bécanes", "contenu" : contenu}
run(host = '0.0.0.0', port = 8080, debug = True, reloader = True)
Here is the template, "gardepage.html":
<!doctype html>
<!-- page_de_garde.tpl -->
<HTML lang="fr">
<HEAD>
<TITLE>{{titre}}</TITLE>
<meta charset="UTF-8">
</HEAD>
<body>
<header>
<h1>Phrases et attrapes</h1>
</header>
<h3>{{titre}}</h3>
<p><image src="turquoise.jpg" alt="125 k4" /></p>
{{!contenu}}
<hr/>
</body>
</html>
The photo is in the same directory as the template and the python file.
Results :
127.0.0.1 - - [13/Mar/2022 11:10:58] "GET /turquoise.jpg HTTP/1.1" 404 746
The page is displayed, the title, the subtitle, but not the photo, there is instead the alternative mention "125 k4".
I wonder what it is, "746". Since I've had so many 404s (!), I've found that terminal messages always follow "404" with another number. I tried to find out about it, but couldn't find anything.
Otherwise, if I click on the html file, it displays without a problem, including the photo.
I tried both suffixes .tpl or .html, there is no difference. I tried .png or .jpg : no difference.
And I get the same result with Python 3.8.1 and Bottle 0.12.7 or with Python 3.10.2 and Bottle 0.12.19.
Thanks for reading me.
Bottle doesn't serve image/js/css automatically - you have to add own function for this.
It is simpler if you put static files in subfolder because then function can recognize this folder in url and run correct function. And this is popular method in other frameworks.
See: Routing Static Files
Example uses subfolder static for this - so you should have files
main.py
pagedegarde.html
static/turquoise.jpg
from bottle import route, run, view, static_file
#route("/")
#view("pagedegarde.html")
def menu() :
contenu = "Moto de l'abbé Khan"
return {"titre" : "Bécanes", "contenu" : contenu}
#route('/static/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='static/')
# or with full path
#return static_file(filepath, root='/full/path/to/static/')
run(host='0.0.0.0', port=8080, debug=True, reloader=True)
And remember to use /static in HTML
<p><image src="/static/turquoise.jpg" alt="125 k4" /></p>
Other frameworks may have the same problem. Some may serve static file only in debug mode but in normal mode they should be executed with web servers like Apache or nginx which should serve static files (because they do this faster)
EDIT:
To serve image in the same folder you would need to use regex to recognize filename in URL
#route('<filepath:re:.*\.(jpg|png|gif)>')
def server_static(filepath):
return static_file(filepath, root='')
The same you would have to do for other static files .css, .js, etc.
And if you would like to server other files for downloading or displaying then you would have to add also other extensions - ie. .csv, .xls, .mov, .mp3, etc.
If you would use regex .* as last route then it would serve all files (which don't match to previous routes)
#route('<filepath:re:.*>')
def server_static(filepath):
return static_file(filepath, root='')
but it is not safe because someone could run ie. http://0.0.0.0:8080/main.py to download source code.
return render_template('homepage.html',imgName=filenameD)
PYTHON
<img src= {{ name }} alt="something" style="width:500px;height:600px;">
HTML
im trying to change the image on my website based on the data I pass to it with python flask but the image does not show up, im using something called jinja?
The image is not shown because you are referencing a non-existent variable in your template. Change your <img> tag to
<img src="{{ imgName }}" alt="something" style="width:500px;height:600px;">
and make sure that filenameD contains the path to your image and not only its name i.e. it should be something like /static/image.png.
Also, always surround your attribute values with "" to prevent XSS attacks, see Flask's security docs.
Try this:
Python
return render_template('homepage.html',name=filename)
HTML
<img src = "{{url_for('static', filename=name) }}" alt="something" style="width:500px;height:600px;">
Your image must be located inside 'static' folder and named as usually ('myimg.png', etc)
I'm working with an IP camera. I can use a URL such as this one to grab a static image off the camera:
http://Username:Password#IP_of_Camera:Port/streaming/channels/1/picture
What I want to do is have python/flask download the image from that URL when the client loads the page, and embed the image into the page using an img tag.
If I have a template that looks something like this:
<html>
<head>
<title>Test</title>
</head>
<body>
<img src="{{ image }}">
</body>
</html>
how do I replace the {{ image }} with the downloaded image?
Would I use urllib/requests to download the image to flask's static folder, replace {{ image }} with something like {{ url_for('static', filename="temp_image.png") }}, and then delete the image from the static folder when the page loads? Would I download it someplace else instead (other than the static folder)? Or is there some other way to do it that keeps the image in memory?
PS. I know it's possible to replace {{ image }} with that URL directly, but that reveals the username/password/IP/port of the camera to the client.
I would add a masking route on flask that fetches and serves the image directly.
Lets say domain.com/image/user1/cam1
Your server would typically make a http request to the camera and once it receives a response, you can straight up serve it as a Response object with appropriate mimetype.
In this case, the image you fetched from camera resides in your RAM.
#app.route('image/<userID>/<camID>')
def fun(userID,camID):
# fetch the picture from appropriate cam
pic = requests.get('http://'+
'Username:Password'+ # dynamically replace user id / password/ auth
'#IP_of_Camera:Port'+ #dynamically replace port / IP
'/streaming/channels/1/picture')
# do processing of pic here..
return Response(pic,mimetype="image/png")
However, if this image needs to be served over and over again, then you might wanna cache it. In which case, I would pick something closer to your approach.
If you want to stream the camera images, it is a whole different ballgame.
import requests
url = "http://Username:Password#IP_of_Camera:Port/streaming/channels/1/picture"
response = requests.get(url)
if response.status_code == 200:
f = open("/your/static/dir/temp.png", 'wb')
f.write(response.content)
f.close()
{{ url_for('static' filename="temp.png") }}
Not sure why you would need to delete it, but I guess you could if you thought that was required
I am trying to display the image on my local machine. I only use the website from my own machine. I am not expecting visit from outside. I found a solution here: Get Flask to show image not located in the static directory, But it doesn't work for me. I have tried:
relative path, abs path. None of them works. Where I did it wrong?
QUESTION:
for test purpose, my file system is like this:
C:/jackson/Python34_workspace/Python34_Projects/Learn-Bottle/app05_rend_local_img/
picuture_gallery/Desert.jpg
views/index.tpl
main.py
python script is this
#bottle.route("/")
def index():
return bottle.template("index.tpl")
#bottle.post('/result')
def result():
return bottle.template("index.tpl")
And this is my template.
<form action="/result" method="POST">
<br>
<input type="submit" value="Submit">
<br>
</form>
<div>
<img src="file:///C:/HSH/Python34_workspace/Python34_Projects/Learn-Bottle/app05_rend_local_img/picture_gallery/Desert.jpg">
</div>
--- Some comment ---
I have tried
src="file:///picuture_gallery/Desert.jpg"
after I clicked submit, it doesn't display. But if I drag it to the browser, it works. How could that be?
An URL using the file procotol is never requested from the server. The client (browser) always looks for it on the local system.
So it doesn't matter how you configure your Bottle application, the browser will not ask it for such an URL.
If you want the Botte application to deliver static files, do something like this:
from bottle import static_file
#route('/static/<filename>')
def server_static(filename):
return static_file(filename, root='/path/to/your/static/files')
I am having some problems using Python to generate an html document. I am attempting to create an HTML list of a directory tree. This is what I have so far:
def list_files(startpath):
for root, dirs, files in os.walk(startpath):
level = root.replace(startpath, '').count(os.sep)
if level <= 1:
print('<li>{}<ul>'.format(os.path.basename(root)))
else:
print('<li>{}'.format(os.path.basename(root)))
for f in files:
last_file = len(files)-1
if f == files[last_file]:
print('<li>{}</li></ul>'.format(f))
elif f == files[0] and level-1 > 0:
print('<ul><li>{}</li>'.format(f))
else:
print('<li>{}</li>'.format(f))
print('</li></ul>')
It seems to work well if there is only the root directory, one level of sub-directories and files. However, adding another level of sub-directories causes there to be problems (because the close tag isn't input enough times at the end I think). But I'm having a hard time getting my head around it.
If it can't be done this way, is there an easier way to do it? I'm using Flask but I'm very inexperienced with templates so perhaps I'm missing something.
You could separate the directory tree generation and its rendering as html.
To generate the tree you could use a simple recursive function:
def make_tree(path):
tree = dict(name=os.path.basename(path), children=[])
try: lst = os.listdir(path)
except OSError:
pass #ignore errors
else:
for name in lst:
fn = os.path.join(path, name)
if os.path.isdir(fn):
tree['children'].append(make_tree(fn))
else:
tree['children'].append(dict(name=name))
return tree
To render it as html you could use jinja2's loop recursive feature:
<!doctype html>
<title>Path: {{ tree.name }}</title>
<h1>{{ tree.name }}</h1>
<ul>
{%- for item in tree.children recursive %}
<li>{{ item.name }}
{%- if item.children -%}
<ul>{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
Put the html into templates/dirtree.html file.
To test it, run the following code and visit http://localhost:8888/:
import os
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def dirtree():
path = os.path.expanduser(u'~')
return render_template('dirtree.html', tree=make_tree(path))
if __name__=="__main__":
app.run(host='localhost', port=8888, debug=True)