Flask: How to get url for dynamically generated image file? - python

from flask import Flask, redirect, url_for
app = Flask(__name__)
#app.route('/')
def index():
generate_img("test.jpg");
return '<img src=' + url_for(filename='test.jpg') + '>'
generate_img() will output a random image to the current directory (same folder as this script).
I am getting 404, I navigate to mydomain.com/test.jpg but it's not there.

Reason of a 404 error is that there is no such view to handle this. To serve images from flask, save the image inside static folder and then you can access image at this url
mydomain.com/static/test.jpg
from flask import Flask, redirect, url_for
app = Flask(__name__)
#app.route('/')
def index():
generate_img("test.jpg"); #save inside static folder
return '<img src=' + url_for('static',filename='test.jpg') + '>'
Static folder is there to serve all the media, be it css, javascript,video or image files with everything accessible at mydomai.com/static/filename. Remember you should not use flask serving from static folder in production. This feature is only for development.

Assuming the image is actually generated (that is, that index() is called), the reason for the 404 is that there is no route that points to the image, so Flask will tell you there is no mydomain.com/test.jpg. A static webserver like Apache or Nginx will by default map paths from a root to URLs, but an ordinary Flask/Werkzeug/WSGI setup will not do that.
Perhaps you want to create a resource that directly returns the image instead?
EDIT: Something similar should be able to serve images.
#app.route("/imgs/<path:path>")
def images(path):
generate_img(path)
fullpath = "./imgs/" + path
resp = flask.make_response(open(fullpath).read())
resp.content_type = "image/jpeg"
return resp
EDIT2: Of course, generate_img could probably be rewritten so it never write to disk but instead return image data directly.

Related

How to return a random gif from a list with Python requests [duplicate]

This question already has answers here:
Serve static files from a CDN rather than Flask in production
(3 answers)
Closed 1 year ago.
I'm using a web server on PythonAnywhere to run a Flask application. All I'm looking to do is randomly output a gif from a list of URLs. I'm looking to utilize the requests library, and I suspect I need the render_template in order to actually pass the image over. I have been dealing with either view function TypeErrors or outputs of plain text to a URL. I've also incorporated PIL and shutil once or twice but to no functional success.
from flask import Flask, render_template
import random
import requests
app = Flask(__name__)
WELCOME_LIST = [
'https://cdn.discordapp.com/attachments/891856529928622080/891865614870806568/rgb.gif'
'https://cdn.discordapp.com/attachments/891856529928622080/891865655542964224/racing.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891897881550802954/comet.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891897942678581278/harujion.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898027126698045/letter.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898085909864479/encore.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898143627677786/gunjou.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898187240050718/haruka.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898241900236830/monster.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898276339646474/probably.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898352617259028/taisho.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898425342316624/tracing.gif',
]
#app.route('/')
def obtainGif():
gif = random.choice(WELCOME_LIST)
response = requests.get(gif)
return response.raw
#app.route('/join')
def output():
finalize = obtainGif
return render_template('home.html', finalize=finalize)
if __name__ == '__main__':
app.run(host='0.0.0.0')
Use the send_file method.
from flask import Flask, render_template, send_file
def obtainGif():
gif = random.choice(WELCOME_LIST)
response = requests.get(gif, stream=True)
return send_file(response.raw, mimetype='image/gif')
You can use {{ variable }} anywhere in your template, not just in the HTML part.
def output():
gif = random.choice(WELCOME_LIST)
return render_template('home.html', gif=gif)
in the home.html file add a script tag in which you are capturing this passed data
<script>
let gif= {{gif|safe}};
</script>
At this point you have the GIF URL inside your java-script code from where you can edit the HTML part of your code to add this GIF inside the <img> tags

Can't show html using Flask

So I have been trying to get used to Flash in python but I've come across a problem. I want that when http://localhost:5000/ is inserted in the browser a html page is displayed. I've tried multiple ways to do this like using the render_template() but that returns me a jinja2.exceptions.TemplateNotFound: index.html. I've also tried a simple return redirect() but that throws something saying the adress was not recognized or understood. When I tried using the url_for() it threw 404 - not found. I really have no idea how to fix this.
# htppserver.py
import flask
import threading
app = Flask(__name__, template_folder="Dashboard/website")
#app.route("/site", methods=["GET"])
#app.route("/", methods=["GET"])
def get_site():
return render_template("index.html")
x = threading.Thread(target=app.run)
x.start()
Currently my dir system looks something like this
main_folder # This is the working directory accordingly to os.getcwd()
├──cogs
│ └──httpserver.py # Source code is here
└──Dashboard
└website
├──...
├──index.html # This is the file I want to show
└──...
Thanks
put your html files in a folder called "templates" in the same directory as the python file that serves

Flask_Scss not compiling scss file in simple app

I'm trying to use Flask-Scss to compile a scss file in my flask app. Here is my app:
from flask import Flask, jsonify, render_template, request
from flask_scss import Scss
app = Flask(__name__)
app.debug = True
Scss(app, static_dir='static', asset_dir='assets/scss/')
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
This file is in a directory that also contains a static directory and assets directory. Furthermore, assets contains a scss directory, which holds the file test.scss. When I run the app, I don't see any css files getting created inside of static. Can someone please tell me what I'm doing wrong?
You have to put absolute path for it to work. Assuming your structure is app/init.py then this should be your code:
Scss(app, static_dir='app/static', asset_dir='app/assets/scss')
NOTE: Don't forget to reload the page for the compiling to happen. If you don't reload the page then scss files will not be compiled to css.
I recommend using libsass, it works for both Sass and SCSS files. After you import sass simply use the compile function with the dirname keyword argument, like this:
sass.compile(dirname=('path/to/source', 'path/to/target'))
You also have the option to set the output style, for example:
sass.compile(dirname=('path/to/source', 'path/to/target'), output_style='compressed')
If you want to watch a file or directory for automatic compilation on every edit use boussole.

Flask-Uploads URL is always a 404

I'm using Flask-Uploads to upload a file and output the URL. However, for some reason the URL always points to a 404! I can see the file in the correct folder, but the URL seems to not be able to find it. Here are the configurations I'm using...
UPLOADS_DEFAULT_URL = os.environ.get("UPLOADS_URL", "http://localhost:5000/")
UPLOADS_DEFAULT_DEST = "app/uploads"
I also have an Upload set defined as:
productUploadSet = UploadSet('plist', extensions=('xlsx', 'csv', 'xls'))
The file is found in "app/uploads/plist/filename.csv" and I'll get a url returned to me like "http://localhost:5000/productlist/filename.csv" but whenever I open the URL it is always a 404. I know that the url method from Flask-Uploads doesn't actually check fi the file exists, but I can see the file is actually there. Is it looking in the wrong place somehow? Thanks for any help.
From Flask's guide to uploading files:
Now one last thing is missing: the serving of the uploaded files. As of Flask 0.5 we can use a function that does that for us:
from flask import send_from_directory
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
Alternatively you can register uploaded_file as build_only rule and use the SharedDataMiddleware. This also works with older versions of Flask:
from werkzeug import SharedDataMiddleware
app.add_url_rule('/uploads/<filename>', 'uploaded_file',
build_only=True)
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/uploads': app.config['UPLOAD_FOLDER']
})
Without implementing one of these, Flask has no idea how to serve the uploaded files.

Flask: How to serve static html?

I am trying to serve a static html file, but returns a 500 error
(a copy of editor.html is on .py and templates directory)
This is all I have tried:
from flask import Flask
app = Flask(__name__, static_url_path='/templates')
#app.route('/')
def hello_world():
#return 'Hello World1!' #this works correctly!
#return render_template('editor.html')
#return render_template('/editor.html')
#return render_template(url_for('templates', filename='editor.html'))
#return app.send_static_file('editor.html') #404 error (Not Found)
return send_from_directory('templates', 'editor.html')
This is the response:
Title: 500 Internal Server Srror
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
Reducing this to the simplest method that'll work:
Put static assets into your static subfolder.
Leave Flask set to the default, don't give it a static_url_path either.
Access static content over the pre-configured /static/ to verify the file works
If you then still want to reuse a static file, use current_app.send_static_file(), and do not use leading / slashes:
from flask import Flask, current_app
app = Flask(__name__)
#app.route('/')
def hello_world():
return current_app.send_static_file('editor.html')
This looks for the file editor.html directly inside the static folder.
This presumes that you saved the above file in a folder that has a static subfolder with a file editor.html inside that subfolder.
Some further notes:
static_url_path changes the URL static files are available at, not the location on the filesystem used to load the data from.
render_template() assumes your file is a Jinja2 template; if it is really just a static file then that is overkill and can lead to errors if there is actual executable syntax in that file that has errors or is missing context.
All the answers are good but what worked well for me is just using the simple function send_file from Flask. This works well when you just need to send an html file as response when host:port/ApiName will show the output of the file in browser
#app.route('/ApiName')
def ApiFunc():
try:
#return send_file('relAdmin/login.html')
return send_file('some-other-directory-than-root/your-file.extension')
except Exception as e:
logging.info(e.args[0])```
send_from_directory and send_file need to be imported from flask.
Your code sample would work if you do the following:
from flask import Flask, send_from_directory
app = Flask(__name__, static_url_path='/templates')
#app.route('/')
def hello_world():
return send_from_directory('templates', 'editor.html')
However, remember if this file loads other files e.g. javascript, css, etc. you would have to define routes for them too.
Also, as far as I understand, this is not the recommended method on production because it's slow.

Categories