Flask not serving image - python

I have a form where users upload a file and its path is stored in a database and the file is stored in '/static/uploads/images/'.
Now in my templates when I call for that image to be displayed I am doing this: <img src="{{ asset_info.picture_location }}" />
The picture_location is the column where the path is being kept. The asset_info is the model object.
For some reason it is returning a 404 when attempting to retrieve the image:
GET /static/uploads/images/motor.gif HTTP/1.1" 404 -even though that is the correct path and I can see the file in there.
Inspecting the url of the broken image icon on the page shows it is retrieving the correct path from the database: http://localhost:5000/static/uploads/images/motor.gif
The response on the client brower says this:
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I've googled around quite a bit but have not had any luck. Is there a separate method I'm supposed to call / build to serve images?
This blueprints info: assets_blueprint = Blueprint('assets', __name__, static_folder='/static', template_folder='templates')
Directory is:
app/
assets/
views.py
asset_models.py
asset_forms.py
other_blueprints/
etc.py
static/
uploads/
images/
motor.gif
app.py
config.py

Figured it out. I had manual settings in the blueprint overriding the default root static folder. I took those out and it defaulted back to serving from the default root static folder, then updated my template code to:
<img src="{{ url_for('static', filename=asset_info.picture_location) }}" /> telling it to retrieve the path from the static root folder. I also then had to append my database location formatting by removing the /static/ from the string concatenation because the url_for('static' .... includes that when it generates the url:
Old:
filename_input = str('static/uploads/images/' + str(request.files['photo'].filename))
New:
filename_input = str('uploads/images/' + str(request.files['photo'].filename))

Related

Flask 404'ing on static content I have in an assets directory

My project structure looks like this:
/project home
app.py
/templates/index.html
/templates/assets
and my index.html file has several references to relative stylesheets that look like this:
<link rel="stylesheet" href="assets/css/slick.css">
<link rel="stylesheet" href="assets/css/slick-theme.css">
Same for various JS files that exist in assets/js. Now when I load the page, I get this error:
Loading failed for the <script> with source “http://localhost:5000/assets/js/popper.min.js”. localhost:5000:564:1
There are many of these messages and in the python debugger I see:
127.0.0.1 - - [24/Dec/2019 18:29:16] "GET /assets/js/main.js HTTP/1.1" 404
I tried googling and changing this line in Flask
STATIC_URL_PATH = '/templates/assets/' # Where the css is stored
STATIC_FOLDER = '/templates/assets/'
app = flask.Flask(__name__, static_folder=STATIC_FOLDER,
static_url_path=STATIC_URL_PATH)
But still when I click the index.html page in templates its able to load fine with all the CSS and JS and images, but from Flask, its like the CSS is stripped out.
First, make sure that the templates folder is in the same directory as your app.py:
.
├── app.py
└── templates
└── assets
Then create the Flask instance like this:
STATIC_FOLDER = 'templates/assets'
app = Flask(__name__,
static_folder=STATIC_FOLDER)
1st, /templates and templates (without /) are 2 different paths. The 1st one refers to a templates folder under the root path / of your system, which certainly isn't the one you want. The 2nd one refers to a templates folder in the same directory, which is the one you want.
2nd, there is no need to specify static_url_path if it's just the same as the static_folder, because that's the default behavior ("Defaults to the name of the static_folder folder").
Then, in your HTML files, instead of hardcoding the paths to the assets folder, let Flask build the URL for you. See the Static Files section of the Flask docs:
To generate URLs for static files, use the special 'static' endpoint
name:
url_for('static', filename='style.css')
By default, it will look for static files under the static folder (ex. static/style.css) because that it is the default value for the static_folder parameter in the Flask constructor. When you set it to templates/assets, Flask will use that and will automatically build the correct URL with url_for.
<link rel="stylesheet" href="{{ url_for('static', filename='css/slick.css') }}">
Note:
Make sure that, when testing the loading of static files, clear your browser's cache first or test your app on private/incognito mode of your browser, to force re-downloading of static files.

STATICFILES_DIR does not work on Apache web-server

I'm testing one and the same application both on the default Django server and on Apache and I see a lot of big differences. I managed to resolve some of them, but at this moment I'm unable to resolve a major difference. So, in project settings.py file I have this code:
MODULES_DIR = BASE_DIR + '/system/modules/'
for item in os.listdir(MODULES_DIR):
stat = os.path.join(MODULES_DIR, item + '/static')
if os.path.isdir(os.path.join(MODULES_DIR, item)):
INSTALLED_APPS += ('system.modules.%s' % item, )
STATICFILES_DIR += (stat, )
APPS_DIR = true
This code is supposed to populate INSTALLED_APPS dynamically, based on the contents of BASE_DIR + '/system/modules/' folder. In other words, if there is a folder inside /modules, this folder becomes an application. Likewise, I build dynamically STATICFILES_DIR - in this case it is supposed, that every single folder/application (which is inside /modules folder) has a /static folder with static contents - js, css etc. For example, it may be such a construct:
\modules
\DefaultModule
__init__.py
urls.py
views.py
\static
test.js
\templates
DefaultModule.html
And DefaultModule.html in this example loads static files like this:
<html>
<head>
{% load static from staticfiles %}
<script type="text/javascript" src="{% static "test.js" %}"></script>
It is rather interesting, but on default Django server this logic works perfectly, so that when I go in my browser to localhost/DefaultModule/, I see a template DefaultModule.html loaded and I see test.js file loaded from http://localhost/DefaultModule/static/. However, on Apache the template is rendered too, but the test.js file is loaded from http://localhost/static/ what eventually results in a 404 NOT FOUND error. So, for some reason Apache server does not take into account STATICFILES_DIR. And yes I checked its (I mean STATICFILES_DIR) contents and it is the same. In both cases STATICFILES_DIR contains modules/DefaultModule/static/, but on Apache it is ignored for some reason. Hope someone can help. Thanks!
I think you should read the Django docs on static files. Looks like you're falling into the simple and old Django Static File Hosting an Apache
Check it out and let us know.

Where to locate user data in Flask application?

I have a flask application where a user's profile image is stored. I originally stored the images in the static directory like so:
application.py
templates/
static/userdata/user/icon.png
Though I don't think this is a good idea because it is not good practice to modify the static directory in production.
I tried making a new userdata folder at root like so:
application.py
templates/
static/
userdata/user/icon.png
Though when I try to access the file with Jinja and HTML,
<img src="/userdata/user/icon.png">
the image does not show. Why is this?
Thanks, in advance.
Use the url_for function
.html
<img src="{{ url_for('userdata', filename='/user/icon.png')}}">
.py
from flask import send_file
#route('/userdata/<filename:filename>')
def get_user_data_files(filename):
return send_file(app.config['USER_DATA_FOLDER'] + filename)

Cannot load Images from Django ImageField in Template

I have a project developed with Django in which users have the ability to upload an image through a form in a view. That part seems to be working correctly in that I can bind the data to a form and save the image in a designated folder within the directory that I'm using for the project's database. However when I go to render a page, I get something similar to the following line (the uploaded image has the filename "2220.jpg"):
GET http://localhost:8000/Users/.../project/database/user_uploads/08-30/2220.jpg 404 (NOT FOUND)
Here's the line in my template that renders the image:
<img class="image" src="{{ entry.image.url }}"/>
The relevant parts of my settings.py:
PROJECT_DIR = os.getcwd()
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'database', 'user_uploads')
MEDIA_URL = ''
STATIC_ROOT = ''
STATIC_URL = '/static/'
The model containing the image:
def getImagePath(instance, filename):
"""Generates a path to save the file. These are timestamped by the
current date and stored in the databases directory.
Returns:
Path for the file.
"""
date = datetime.date.today().strftime('%Y-%m-%d')
return os.path.join(
os.getcwd(), 'database', 'user_uploads', date, filename)
class Entry(models.Model):
# Other code omitted
image = models.ImageField(upload_to=getImagePath)
I'm guessing there's some URL configuration I'm missing because it seems like it's asking for the image to be served via localhost (or more generally my host name) rather than just a directory on the filesystem. The file location is correct, it just seems to be executing an HTTP request for it instead of just getting it directly. What am I missing? I'm happy to provide any additional information for clarity.
Thank you in advance!
you have to setup media serving.
https://docs.djangoproject.com/en/dev/howto/static-files/#serving-files-uploaded-by-a-user
In addition to montiniz's answer, the following thread helped me out:
Django MEDIA_URL and MEDIA_ROOT
Basically what I was missing was the URL configuration for serving files from MEDIA_ROOT. One other thing is that calling the url() parameter on a Django ImageField returns the fully qualified URL name - that is, the file's full location. All you need to serve the image from the template is its location within MEDIA_ROOT. In my case, this setting was 'database/user_uploads' and the image was located at '2013-09-02/images/2220.jpg'.
Therefore the url I needed was:
'localhost:8080/media/database/user_uploads/2013-09-02/images/2220.jpg'.
Hope this helps anyone with the same issue!

Cannot show image from STATIC_FOLDER in Flask template

I set folder for static files like this
app.config['STATIC_FOLDER'] = 'tmp'
In template i use img tag to show an image stored in /tmp:
<img src='IKE2low.jpg' width="200" height="85">
In firebug i see 404 error instead of image. Please tell me what did i do wrong?
Thanks in advance.
I'm not sure what is this STATIC_FOLDER configuration item you are using. Where did you find it?
There are actually two arguments to the Flask class constructor that govern the configuration of static files:
static_folder: defaults to "static". This is the prefix that you have to use in URLs to access the static files.
static_url_path: this is the disk location of the static folder. By default this value is the same as the static_folder setting.
For example, if you use this configuration:
from flask import Flask
app = Flask(__name__, static_url_path = "/tmp", static_folder = "tmp")
Then you can access your images as follows:
<img src='/tmp/IKE2low.jpg' width="200" height="85">
You can also remove the need to have a prefix in the URLs as follows:
from flask import Flask
app = Flask(__name__, static_url_path = "", static_folder = "tmp")
And then you can access your images as:
<img src='/IKE2low.jpg' width="200" height="85">
Note that you still need to have a root /.
But the best way to do this is to not reference image paths explicitly and instead use url_for to generate the correct URLs. If you are using Jinja2 templates that would be:
<img src="{{ url_for('static', filename = 'IKE2low.jpg') }}" width="200" height="85">
This last expression would work regardless of where and how the static files are configured.

Categories