laike9m laike9m - 4 months ago 153
Python Question

Flask, Keep getting 404 serving static files using send_static_file

I followed the instructions from How to serve static files in Flask, but still couldn't get it working.

Here's my project structure:

Project_path
|
+--app
| |
| +--main.py
+--static
|
+--js
|
+--jquery-1.11.2.min.js


Here's
main.py
:

@app.route('/js/<path:path>')
def serve_static(path):
root_dir = os.path.dirname(os.getcwd())
print(os.path.join(root_dir, 'static', 'js', path))
return app.send_static_file(os.path.join(root_dir, 'static', 'js', path))


Here's
index.html
:

...
<script type="text/javascript" src="/js/jquery-1.11.2.min.js"></script>
...


And when I visit
/
, I could see the correct path of javascript file printed on the screen

which is
Project_path/static/js/jquery-1.11.2.min.js
.

But still, I got

127.0.0.1 - - [22/Dec/2014 11:26:30] "GET /js/jquery-1.11.2.min.js HTTP/1.1" 404 -


Any help is appreciated.

EDIT

After stepping through the
send_static_file
method, I find out what's going on. Basically, I shouldn't use abspath as argument, flask has a judgement in
send_static_file
:

if os.path.isabs(filename) or \
filename == '..' or \
filename.startswith('../'):
raise NotFound()


And since the
filename
I passed into is a abspath, flask raise
NotFound()
.

It seems that what it supposed to be passed in is a relative path to
self.static_folder
(self is
<Flask 'main'>
), which, in my project, is
Project_name/app/static
. However, I didn't set
static_folder
myself which means flask thinks the static folder should be there.

I'm still trying to figure out what to do.

Answer

Finally got it working. use flask.send_from_directory

from flask import send_from_directory

@app.route('/js/<path:filename>')
def serve_static(filename):
    root_dir = os.path.dirname(os.getcwd())
    return send_from_directory(os.path.join(root_dir, 'static', 'js'), filename)

It is now clear to me that flask really hate people putting app.py or in my case main.py into a subdirectory. Use send_static_file only if your static folder is what flask thinks to be, i.e. a folder with name static in the same directory with app.py.