38

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.

3
  • Why are you going through all this? Flask will automatically serve static files. You don't need to write a view for it. Commented Dec 22, 2014 at 7:22
  • 2
    @BurhanKhalid Not quite true. flask serves static files automatically if 1. set src="/static/js/xxx.js"; 2. static folder is in the same directly with app.py. Commented Dec 22, 2014 at 7:38
  • for me this one worked : @app.route('/static/<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) Commented Jul 12, 2016 at 20:50

5 Answers 5

59

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.

Sign up to request clarification or add additional context in comments.

3 Comments

you can replace root_dir with '.' - return send_from_directory(os.path.join('.', 'static', 'js'), filename)
This answer is not completely true. For blueprints you can set another static folder and this static folder could be with any name.
Dear future me: Careful when passing a relative path as the first argument to send_from_directory. It will NOT be interpreted relative to the current working directory, if that is what you are after.
20

All you need to do is, pass the static_folder parameter to the initiator:

static_url_path – can be used to specify a different path for the static files on the web. Defaults to the name of the static_folder folder.

static_folder – the folder with static files that should be served at static_url_path. Defaults to the 'static' folder in the root path of the application.

app = Flask(__name__, static_folder=os.path.abspath('/foo/bar/zoo/'))

Now, flask will look for a directory named static in /foo/bar/zoo from where to serve static files. You only use send_from_directory if you are serving media files which may not be in the same location as static files.

7 Comments

What is the correct static_url_path for my project? And what should be the src attribute in html?
Its the fully qualified path to the parent directory of static, and you don't need to make any changes in your src attribute, it will be exactly as in the documentation.
So it's static_url_path=Project_path/static/ and src="/js/jquery-1.11.2.min.js", correct?
No, remove the static part, and please read the documentation which explains it a lot better than I can in these comments.
After many tests, I'm sure that if I want to put static files in seperate folders(css, js, ...), it's not possible to serve them only by modifying static_url_path and static_folder. Using url_for in jinja2 would work but that's another story.
|
1

You forgot to add 'static' in the last os.path.join in the return clause.

1 Comment

I thought you are correct, but after adding static, it still gives me 404 error.
1

for me this one worked :

@app.route('/static/<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)       

beside adding this script into init

app._static_folder = os.path.abspath("static/")
app = Flask(__name__)

into __init__.py

1 Comment

i also call static files in my HTML code in this way : <link rel="stylesheet" href="static/css/homestyle.css"> <link rel="stylesheet" href="static/css/bootstrap.min.css">
0

One possible cause of 404 error for pages you just added (even if programmed correctly), is if you have previous versions of the script (.py file) still running: make sure to close out and end (terminate) the process.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.