Flask not serving pictures - python

I created a small Flask app for the purpose of processing and presenting data for my local consumption on my local machine. My Flask app processes data in a subfolder and then opens a webpage to display the processed data. Everything looks great except that images are not being served. For example the resulting HTMl source will have something like:
<img src="/Users/username/Desktop/datafolder/pics/pic1.png" alt="pic1">
however there will be no image. The paths are correct so I am guessing it has to do with how images are passed, or not passed, to Flask in the render_template. Perhaps there is a way to specify a media directory as I see in this django post?
Any suggestions on how I might be able to include images would be very welcome.
best regards,
zach cp
Edit: As mentioned in the answers and comments, all static files must be in the designated static directory. My use of the "file://" construct triggered the browser to give an error message:
"Not allowed to load local resource: file:///Users/username/Desktop/datafolder/pics/pic1.png"
which is why I could not see the image. I could use any of the solutions below that result in the images I want to have served in the designated static folder.

The Flask application defaults the files where it attempts to serve static files as the "static" path in the root directory for the application. Thus, if you run your program in...
C:\Users\username\Desktop\MyApp
the static folder will be
C:\Users\username\Desktop\MyApp\Static
Thus, when attempting to serve
/Users/username/Desktop/datafolder/pics/pic1.png
the file Flask will try to serve will actually be...
C:\Users\username\Desktop\MyApp\Static\Users\username\Desktop\datafolder\pics\pic1.png
This probably isn't right.
Therefore, you can do a few things:
Change the files that are being processed to the "static" folder of where you Flask app is running from, and make the HTML src value relative to that directory
Set the static_folder parameter on the Flask constructor. This allows you to set specifically where the static files will be served from.
app = Flask(static_folder='C:\\Some\\Directory')
As some comments have suggested, change to using the file:// type. If it doesn't work, then post what you're trying, because it should work :)

Well,you'd better take a look at this: http://flask.pocoo.org/docs/quickstart/#static-files
What you need to do:
cd path/to/your/flask/app
mkdir static
mv /Users/username/Desktop/datafolder/pics/pic1.png /static
use <img src="/static/pic1.png" alt="pic1"> in your template.

The Flask application defaults the files where it attempts to serve static files as the "static" path in the root directory for the application.
Create Static folder & paste the images in that & give the path as \Static\Img.png

Related

How to get static files to work when testing the Flask REST API with flask_testing framework

I'm making a Flask REST API with Flask-RESTX library. One part of API are also calls that generate PDF documents. To generate documents I'm using some font files and images from the static/ directory. Everything is working when I'm running the API, but when I'm trying to call the same calls from my tests I'm getting an error that files used in PDF generation can't be found.
OSError: Cannot open resource "static/logo.png"
I'm guessing the reason for this is that the path to static folder is different when running tests. Is there a nice way to use the same path to static files in tests or there needs to be some custom path-switching logic depending on the run type (development, production, testing).
Folder structure:
/src
/application
/main
app.py
/test
test.py
/static
logo.png
I access the assets in my application as such:
static/logo.png
So I solved the issue by changing the current working directory inside tests. Following this SO post. So I implemented the method:
from contextlib import contextmanager
#contextmanager
def cwd(path):
old_pwd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(old_pwd)
And then during my tests I then change the path during the test:
def simple_test():
# default CWD
with cwd('../../'):
# code inside this block, and only inside this block, is in the new directory
perform_call()
# default CWD

How to access file from an external folder in flask server?

I am new to flask and am very confused regarding including libraries from external folders into the html template. I know how to include from the static folder, but I want to keep my code and the library files in separate folders. So, my directory structure is something like:
./main_directory
|
|_./Code
| |_./flask_script.py
| |_./static
|
|_./Libraries
I know about the send_from_directory() function but I don't understand exactly how to use it. The most common thing I have seen is:
#app.route('/cdn/<path:filename>')
def custom_static(filename):
return send_from_directory(app.config['CUSTOM_STATIC_PATH'], filename)
Which is from another StackOverflow answer. But here what is cdn in this case? Also, what is the value of app.confg['CUSTOM_STATIC_PATH'] set to? And what all should be done in the HTML template to make this work?
In general serving static files with flask is only good for development. Realistically, when going live it is advised to serve static files otherwise, for example having a web server in front of your app and delegating file serving to it, or putting the files in a file store, like AWS S3.
Regarding your custom_static route, cdn in this case is simply a url prefix (it can be anything), you can then address your static assets from templates like <img src="/cdn/test.jpg">. (The cdn prefix can give you a hint that these files are later moved to a CDN and aren't served by flask in production).
app.config['CUSTOM_STATIC_PATH'] should be set to the absolute path to the directory containing your custom static files.

GAE Python: how get last modified date of static file

I'm adding some static files to my Python app on Google app engine. I do it like this, as described here.
app.yaml:
handlers:
- url: /stylesheets
static_dir: stylesheets
I put my files in the subdirectory stylesheets within the my_project_app folder.
How can I get the last modified date of a file in stylesheets?
When you indicate the a file or directory is static by default you can not access it with your application, which means you can't get the modification date. You can think of the static files as being uploaded to a different machine that is configured to to serve static files.
You can upload the file both as a static file and an application resource (or use a symlink), but this means it counts twice against the quota. Recently this has been made easier with the addition of the application_readable option. Setting it to true in app.yaml essentially does the same thing. (see: https://cloud.google.com/appengine/docs/python/config/appconfig#Static_Directory_Handlers ).
Once your application can read the file you can use the standard os library to read the whatever information you need.
Answer is simple make static files accessible that is all.
https://cloud.google.com/appengine/docs/python/config/appconfig#Python_app_yaml_Static_file_handlers
application_readable
Optional. By default, files declared in static file handlers are
uploaded as static data and are only served to end users, they cannot
be read by an application. If this field is set to true, the files are
also uploaded as code data so your application can read them. Both
uploads are charged against your code and static data storage resource
quotas.
use such code to locate file relative to python file - sometimes you need .. to go up.
os.path.join(os.path.dirname(__file__), 'template', 'list_tbody_part.html')

Serve static files from sub-app in web.py

I am writing a web-app in web.py (a rewrite/extension of mongs) which I want to function both as a standalone application, and as a sub-app that requests can be forwarded to. The issue that I am having is that when it is used as a sub-app, static files cannot easily be served from its own static directory. Since I intend to distribute this (and not require users to combine the files into their project's static directory) I want the directory structure to be:
app_that_is_using_mongs (not mine)
static (which holds the app's static files - also not mine)
mongs (my subapp)
main.py (the code for mongs)
view (holds templates)
static (the static folder for mongs)
main.py (the code for the app that is using mongs)
...so that the entire mongs directory is separated from whatever app is using it.
I have considered a few possibilities for getting this to work:
Using a request handler that reads and outputs the files from the static directory, like:
cwd = os.path.dirname(__file__) + '/' # get current working directory
class Static:
def GET(self, filename):
"""searches for and returns a requested static file or 404s out"""
try:
return open(cwd + 'static/' + filename, 'r').read()
except:
web.application.notfound(app) # file not found
I am not sure about the performance of this solution for large files, and it seems like this should be something web.py can do on its own.
Adding another static directory by accessing the cherry.py staticdir tool through web.py... I'm not sure how to do something like this (interacting directly with the server that web.py is running on), and I don't think it would still work if I switched to a Gunicorn server (or any server but cherry.py).
Fixing the way that web.py handles static files to make it more extendable... If there is no other way, then rewriting this portion of web.py and maybe getting it pushed into the main repo is probably the best way.
So, what is the best way to do this?
In web.py the static assets aren't served through the application router. Instead the http server has a check weather the request url starts with /static. This means that weather you have a sub-application or not, the /static/... maps directly to the static directory in the root application.
Your first idea of building a static class will definitely work, but you are right that there is a definite performance implication - though, you'd have to benchmark it to really know how bad it is.
Another option, which is operationally worse, but is a temporary fix is to create a soft-link from the static directory of the parent app, into the sub-application's static directory. i.e.
parent_app/
static/
sub_app/ -> parent_app/sub_app/static/sub_app
...
sub_app/
static/
sub_app/
...
Then, when you want to access a static asset from sub_app, you would hit a url like: /static/sub_app/asset. Since this url starts with /static, it will get caught by the http server and redirect to the static directory, following the soft link, and resolves to the actual asset. Because of the sub_app directory, this solution will work when running the sub_app directly, or running the parent_app. You will have to setup this soft link on every server you deploy to, and for every development environment, which makes this less than ideal.

Django can't find my non-python files!

I can't, for the life of me, get Django to find my JavaScript files! I am trying to plug in a custom widget to the admin page, like so:
class MarkItUpWidget(forms.Textarea):
class Media:
js = (
'js/jquery.js',
'js/markitup/jquery.markitup.js',
'js/markitup/sets/markdown/set.js',
'js/markitup.init.js',
)
css = {
'screen': (
'js/markitup/skins/simple/style.css',
'js/markitup/sets/markdown/style.css',
)
}
However, when this code is inserted on my admin page, all of the links are broken, I can't get to any of my JavaScript files. My settings file looks like this: http://pastebin.com/qFVqUXyG
Is there something I am doing wrong? I'm somewhat new to Django.
I guess you're using django-admin runserver to test your website. In that case, have a look at "How to serve static files" (but don't ignore the big fat disclaimer).
Once you're ready to deploy, this chapter contains all the information (provided you go the standard route of Apache/mod_wsgi)
I don't know what the "django way" to include js files is, but I just use a simple regular include in the template, its great since you can dynamically generate the location / filename for these.. oh and if you are using django's test server I don't know how to get it to recognize these or if it even can but all you need is to run an apache server on your local machine and then put the files in the localhost directory and you can include them through localhost by including their full path in the template (i.e., http://localhost/myfiledirectory/myfile.js), also something I do is use amazon s3 to host files since you then get a url for them on there (not that you asked about this but its a quick way to host files if you don't have apache running locally)
Basically, my understanding of Django is that it works differently than a PHP framework, for example, as the files for Django don't sit (or don't need to at least) in the web path (i.e. they do not need to be accessible through the host path but can be anywhere on the machine) this is good for providing extra security, etc but it also means, that to give files a url to download them they need to be in the web hosting path, others may know how to make django do this directly but my quick and dirty method of putting them on the localhost path will work if thats all you're after.

Categories

Resources