Images not correctly displayed using Flask - python

I'm setting an application where I need to display some image. My images are located outside of my app's folder, that's why I've used this:
#app.route('/<path:filename>')
def download_file(filename):
return send_from_directory(MEDIA_FOLDER, filename=filename, as_attachment=True)
The architecture of my folders is:
--images1
|__ image1.png
|__ image2.png
--images2
|__ image3.png
|__ image4.png
--web
|__ app.py
|__ templates
|__ index.html
I've stored all my images path in a list as:
images_path = ['image1.png', 'image2.png', ...]
At the moment, I've tried to display the images as:
{% for image in images_path %}
<img src="{{ url_for('download_file', filename="{{ image }}") }}">
Using this, it displays always the same image. In my example the image1.png.
I've tried to check if the for loop works, and it works.
I've tried this:
{{ image }} CHECKER
<img src="{{ url_for('download_file', filename="{{ image }}") }}">
and it displays on my page:
>>>
image1.png CHECKER then the `image1.png`
image2.png CHECKER but also `image1.png`
UPDATE 1
In my app.py, I've added this:
#app.route('/<path:filename>')
def download_file(filename):
images_folder = [images1, images2]
try:
for image_folder in imagesfolder:
MEDIA_FOLDER = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + str(image_folder) + "\\"
return send_from_directory(MEDIA_FOLDER, filename=filename, as_attachment=True)
except FileNotFoundError:
abort(404)
and on my template.html, I've added this:
{% for image in images_path %}
<img src="{{ url_for('download_file', filename=image) }}">
How can I correctly set the path here?
How can I link the images and its directory?
UPDATE 2
I've changed my script by:
#app.route('/<path:filename>')
def download_file(filename):
try:
return send_file(filename, as_attachment=True)
except FileNotFoundError:
abort(404)
The filename will be defined by:
>>>> filename = str(os.getcwd()) + str(list_machine[i]) + str(elem)
When I inspect the elements on my page, the URL seems to be right but the image is not displayed.
How can I display all the images stored in my folders?
Thanks in advance.

You could try this:
<img src="{{ url_for('download_file', filename=image) }}">
with the image variable defined as: image = str(os.getcwd()) + '/path/to/image'
You must define this variable by listing your files, you can use: os.listdir('path/directory').
Your function named download_file should be:
#app.route('/<path:filename>')
def download_file(filename):
try:
filename=os.path.join(app.root_path, filename)
return send_file(filename)
except FileNotFoundError:
abort(404)
Don't forget to import the send_file function.
It works for me. Hope it helps.

The problem doesn't come from {{ image }} but I don't see in your code {% endfor %} after the html img.
So the correct code is :
{% for image in images_path %}
<img src="{{ url_for('download_file', filename="{{ image }}") }}">
{% endfor %}
UPDATE 1:
I think you make several mistakes in your code :
#app.route('/<path:filename>')
def download_file(filename):
images_folder = ['images1', 'images2']
MEDIA_FOLDER = []
try:
for image_folder in imagesfolder:
MEDIA_FOLDER.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + str(image_folder) + "\\")
return send_from_directory(MEDIA_FOLDER, filename=filename, as_attachment=True)
except FileNotFoundError:
abort(404)

Related

Is there a way to parse a file through to a <source> tag in HTML

I'm trying to make a private file host and I have it set to return a send_file() when the, for example, /media/someSong.mp3 url is called.
But I want to make it more styled so when you visit /media/someSong.mp3, instead of your browser trying to play that MP3 in it, it will use a HTML page with a tag that parses the send_file() sent by an argument.
Currently, I have this:
#app.route('/media/<mediaID>')
def mediaStuff(mediaID):
try:
return render_template('parse-it.html', title=title, media_file=send_file(f'./media/{mediaID}'))
# return send_file(f'./media/{mediaID}')
except FileNotFoundError:
return 'The media you tried to view doesn\'t exist.'
And here is what I have in my templates/parse-it.html file:
{% extends "base.html" %}
{% block content %}
<h1>You are now viewing ...!</h1>
<source src={{media_file}}>
{% endblock %}
However all I see is <Response 200 OK> or something like that. No file to be seen!
Would I use a get_file() and then return Response(getfileVar) in that media_file argument?
send_file returns a Response object. It makes no sense to pass this to the template.
So you need two endpoints. One to display your website containing the media element and one to stream the file from the directory. I recommend using send_from_directory for this.
This is a simple example that lists all files within a directory and offers them for playback or viewing. The distinction is made based on the mime type of the file. This is determined via guess_type.
The exmpale uses the instance path to ensure separation of files and application.
import os
from flask import (
Flask,
render_template,
send_from_directory
)
from mimetypes import guess_type
app = Flask(__name__)
app.config['MEDIA_FOLDER'] = os.path.join(app.instance_path, 'media')
try:
os.makedirs(app.config['MEDIA_FOLDER'])
except:
pass
def listfiles(target):
for filename in os.listdir(target):
mimetype = guess_type(os.path.join(target, filename))
yield (
filename,
mimetype,
)
#app.route('/')
def index():
files = listfiles(app.config['MEDIA_FOLDER'])
return render_template('index.html', **locals())
#app.route('/media/<path:filename>')
def media(filename):
return send_from_directory(
app.config['MEDIA_FOLDER'],
filename
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% for filename, type in files -%}
<div>
{% set mimetype, encoding = type -%}
{% if mimetype.startswith('audio') -%}
<audio controls>
<source src="{{ url_for('media', filename=filename) }}" type="{{ mimetype }}">
</audio>
{% elif mimetype.startswith('image') -%}
<img src="{{ url_for('media', filename=filename) }}" />
{% endif -%}
</div>
{% endfor -%}
</body>
</html>

django loop static files directory

Iam trying to loop thru images in static/folder. I can loop thru images in main 'static' folder but when i put them in 'static/folder' iam not sure how to do it in html.
my html lines(works when img in main 'static' folder)
{% for file in files %}
<img src=" {% static file %}" height="800">
<p>File name:{{ file }}</p>
{% endfor %}
my views.py
def album1(request):
images = '/home/michal/PycharmProjects/Family/gallery/static/'
files = os.listdir(os.path.join(images))
context = {'files': files}
return render(request, 'gallery/album1/main.html', context)
If i change views to:
def album1(request):
images = '/home/michal/PycharmProjects/Family/gallery/static/'
files = os.listdir(os.path.join(images, 'folder'))
context = {'files': files}
return render(request, 'gallery/album1/main.html', context)
It loops filenames in 'static/folder/' as expected, but then i cant figure out how to change it in html ,as its adding file names to: /static/{{ file }} instead to /static/folder/{{ file }}.
I think iam missing something or something need changing in load static on this particular page?
{% load static %} # either here
<img src=" {% static file %}"> # or here?
You prepend the filenames with the name of the folder:
from os.path import join
def album1(request):
images = '/home/michal/PycharmProjects/Family/gallery/static/'
files = os.listdir(join(images, 'folder'))
context = {'files': [join(folder, file) for file in files]}
return render(request, 'gallery/album1/main.html', context)
You can slice in the template with the |slice template filter [Django-doc]:
{% for file in files|slice:':21' %}
<img src=" {% static file %}" height="800">
<p>File name:{{ file }}</p>
{% endfor %}
But it is more efficient to do this in the view, since you save cycles on by performing less join calls, and furthermore the templates are less efficient than Python code.

How to display images from folder in Python html and flask

I am very new to python and Flask.
I have a folder with a list of jpeg images. I have to display them in my demo application with flask as below,
My app.py :
#app.route("/")
def home():
return render_template('home.html')
My home.html:
<img id="person" src={{ url_for('static',filename='pferson_folder/000_1.jpg') }}>
In the above code, I don't want to hardcode the images in the HTML tag. it needs to take the image source from folder dynamically.
Would you please help me with this. Thank you.
You can read all the file names out of the directory using os.listdir('Your path') and pass the array into the template:
Something like:
# Inside app.py
import os
#app.route('/')
def home():
image_names = os.listdir('Your path to images folder')
render_template('home.html', image_name=image_names)
And inside your template:
{% for name in image_names %}
<img src="{{ url_for('static', filename='pferson_folder/' + name) }}" >
{% endfor %}
Then you don't have to hardcode the names.

Jinja2 Using images in HTML

I wasted a lot of time to find out what is wrong. I need your help now.
I want to render template with image from my filesystem. But it is not working.
Path - string that contains file name
#app.route('/', methods=['GET'])
def main():
return render_template('main.html',image = path)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<h2></h2>
<form method="post" enctype="multipart/form-data" action="/uploader">
<input type="file" name="file">
<button type="submit">Upload</button>
</form>
<img src={{ url_for('static', filename = image) }} >//i can't figure how to change this to use {{image}}
</body>
</html>
Just generate full image path in your view and pass it to your template
#app.route('/', methods=['GET'])
def main():
#path is filename string
image_file = url_for('static', filename=path)
return render_template('main.html', image_file=image_file)
and then just use it as full link
<img src={{ image_file}} >
if you have image file (with filename which stored in path) in your static folder this should work
If you was set the static folder like that (or other methods):
from flask import Flask
app = Flask(__name__, static_folder='static')
#app.route('/', methods=['GET'])
def main():
return render_template('main.html', image = url_for("static", filename=path))
or shorter:
return render_template('main.html', image='/static/' + path))
after you will put your image in /static folder you can get it from template:
<img src="{{image)}}">
I think something like this should work.
<img src="{{ url_for('static', filename='image') }}">
Where 'image' refers to the path of the image file inside static folder. Make sure to use the full name of image file along with its file type i.e. jpg, png etc.

Flask: How to get uploads folder path

I'm trying to get the uploads folder path.
UPLOAD_FOLDER = '/uploads'
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
I upload the images in the path:
.
└── uploads
└── img_articles
└── 2017
└── 02
└── image.jpg
I want to use image.jpg in a Jinja Template
{% extends "layout.html" %}
{% block content %}
<div class="container">
<img src="{{image_path}}" alt="">
</div>
{% endblock %}
What should I do?
Have a look at the Uploading Files Pattern in the information for the Pros.
Define a route for your uploads:
from flask import send_from_directory
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
In your template you can then use the route to get your filename
<img src="{{ url_for('uploaded_file', filename='yourimage.jpg') }}">

Categories