skip to Main Content

Say I have project structure:

- app.py // flask server
- static/
  - index.html
  - subfolder/
    - index.html
    - main.js

In Flask I can go:

@app.route('/')
def index():
    return send_from_directory(os.getcwd() + "/static", "index.html")

and serve the index file within the root dir… But it will not accept subfolders or any other file.

I have searched following the following:
How to serve static files in Flask
How to serve static file from static folder using Flask
Flask: How to serve static html?

and found I can do:

@app.route('/<path:path>')
def index(path):
    return send_from_directory(os.getcwd() + "/static", path)

But this requires you to explicitly supply index.html to the end of all routes.

An alternative is then to use:

@app.route('/<path:path>' , defaults={'path': 'index.html'})
def index(path):
    print(f"looking in: {os.getcwd()}/static{path}")
    return send_from_directory(os.getcwd() + "/static", path)

But then this doesn’t supply subdirectories, and will always redirect you to /static/index.html. Furthermore, if you do supply an explicit index.html to the url, it will render the html correctly, but not the .js file with the error: Uncaught SyntaxError: Unexpected token '<' (at main.js:1:1)

main.js:

console.log("hello")

subfolder/index.html:

<head>
<script src="main.js"></script>
</head>
<body>
<h1>henlo</h1>
</body>

I just want to serve a static folder. How do I do this? The documentation itself says:

Static Files:
Dynamic web applications also need static files. That’s usually where the CSS and JavaScript files are coming from. Ideally your web server is configured to serve them for you, but during development Flask can do that as well. Just create a folder called static in your package or next to your module and it will be available at /static on the application.

To generate URLs for static files, use the special 'static' endpoint name:

url_for('static', filename='style.css')
The file has to be stored on the filesystem as static/style.css.

but of course, url_for does not exist as a function in python nor any dependency or component of the flask module, and even if it did, there is no example of how to use it.

2

Answers


  1. In Flask, you can serve all files in a directory using the send_from_directory function. Additionally, to set a default entrance point (like index.html), you can create a route that handles requests to the root path ("/") and returns the content of the index.html file.

    Here’s an example:

    from flask import Flask, send_from_directory
    
    app = Flask(__name__)
    
    # Serve all files in the 'static' directory
    @app.route('/static/<path:filename>')
    def serve_static(filename):
        return send_from_directory('static', filename)
    
    # Set the default entrance point to 'index.html'
    @app.route('/')
    def index():
        return send_from_directory('static', 'index.html')
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    Login or Signup to reply.
  2. Within static pages, url_for is not available. The prerequisite for use is a dynamic template. Files can then be imported from the static folder or a subfolder via url_for('static', filename=...), as described in the documentation.

    Two properties are relevant to configuring the static folder, which can be defined when instantiating the application. The static_folder attribute defines the path to the folder in which the static files are located. static_url_path defines a URL prefix to access static files on the web. The default value is static.

    As I understand you, you want to serve static HTML files and their assets without using a URL prefix. The static folder with subfolders should serve as the storage location. You refer to files used within the HTML pages with relative paths.
    To achieve this you can simply assign an empty string to the static_url_path attribute.

    from flask import Flask
    
    app = Flask(
        __name__, 
        static_url_path=''
    )
    
    @app.route('/')
    def index():
        return app.send_static_file('index.html')
    

    If you want to point to the file in the folder for each subdirectory without explicitly specifying index.html, you can define your own endpoint using send_from_directory. However, this does not accept relative path information.

    from flask import Flask, send_from_directory
    import os
    
    app = Flask(__name__)
    
    @app.route('/')
    @app.route('/<path:filename>')
    def index(filename=''):
        if not filename 
            or filename.endswith('/') 
            or os.path.isdir(os.path.join(app.static_folder, filename)):
            
            filename = os.path.join(filename, 'index.html')
        return send_from_directory(app.static_folder, filename)
    

    Keep in mind that the actual purpose of a Flask application is not to provide a server to serve static files.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search