I'm working on a simple file server, where you can upload files and these files go to a db and a upload folder. Now, it only needs a list of linked files.
Right now I have this:
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
The uploaded file shows right after uploaded. That is why I need those links.
from os import listdir
from os.path import isfile, join, abspath, dirname
#app.route('/files')
def files():
files = [f for f in listdir(app.config['UPLOAD_FOLDER']) if isfile(join(app.config['UPLOAD_FOLDER'], f))]
return render_template("files.html", files=files)
files.html
{% for file in files %}
{{ file }} <br />
{% endfor %}
Related
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>
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.
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.
I am trying to make a loop to show images in a slideshow in flask, but I want to take the images that put the name of the image, I am trying with glob but this gives the following error:TypeError: 'module' object is not callable
python code
from flask import Flask, render_template
import glob
import os.path
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
ruta_imagenes = glob(os.path.join(app.static_folder, "img"))
render_template('index.html',ruta_imagenes=ruta_imagenes )
if __name__ == ('__main__'):
app.run(debug=True)
HTML
<div class="carousel-inner">
{% for _, ruta in enumerate(rutas_imagenes) %}
<div class="carousel-item ">
{% if _ == 0 %}active{% endif %}
<img src="{{ ruta }}" class="d-block w-100" alt="...">
</div>
{% endfor %}
</div>
You're importing glob and then just calling it. But glob is a module.
What you want is either
import glob
glob.glob(os.path.join(app.static_folder, "img"))
or
from glob import glob
glob(os.path.join(app.static_folder, "img"))
As #blueteeth mentioned you are importing glob module, which is not callable. You probably meant glob.glob() - a function, inside the glob module.
However, even then, glob is probably not what you are looking for. If you want to get a list of images you need to read files in the directory with something like:
ruta_imagenes = []
for root, dir, file in os.walk(path):
ruta_imagenes.append(file)
And, of course, don't forget to pass these images to your template
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)