Serving with speed: Static Files in FastAPI

Sarumathy P
featurepreneur
Published in
5 min readMay 28, 2023

FastAPI is a modern web framework for building APIs with Python.

FASTAPI represents a significant advancement in API development technology for Python developers. Its ability to leverage Python’s type hints and async/await syntax to deliver high-performance APIs makes it a compelling choice for developers who want to build scalable, production-ready APIs quickly and efficiently.

This article focuses on serving static files in FastAPI by importing images to our app that reside in a directory.

In FastAPI, static files such as images, CSS files, JavaScript files, or PDFs are typically served directly by the web server instead of being handled by your application code. This improves performance and allows the webserver to efficiently serve these static files.

Let's first create a FastAPI endpoint to render our template(index.html)

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
import uvicorn


app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get('/')
def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})

if __name__ == "__main__":

uvicorn.run(
"main:app",
host = "0.0.0.0",
port = 8036,
reload = True
)

To know about rendering templates, Refer to this article

https://medium.com/featurepreneur/fastapi-render-template-redirection-c98a26ae1e2a

Directory Structure:

Here is the index.html file to display the name “Image Gallery”.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<title>Image Gallery</title>
</head>
<body>
<div class="container mt-5">
<h1 class="text-center mb-5">Image Gallery</h1>
</div>
</body>
</html>

This file makes use of Bootstrap 5 for styling.

Run the program using the command

python app.py

After running the program locally, when a request is made using the URL http://0.0.0.0:8036,

Now, Let's create a folder called “static” and add images to it.

I have downloaded a few images and added them to the static folder. Now let's see how to render them.

app.mount("/static", StaticFiles(directory="static"), name="static")

This line of code is used to mount a static file directory in FastAPI.

  • app: Refers to the FastAPI application instance.
  • .mount(): Method used to mount a specific path to a directory.
  • "/static": The URL path or endpoint at which the static files will be served. In this case, it's /static.
  • StaticFiles(directory="static"): An instance of the StaticFiles the class provided by FastAPI. It is responsible for serving the static files from the specified directory. Should be imported as
from fastapi.staticfiles import StaticFiles
  • directory="static": Specifies the directory from which static files will be served. In this example, it's the "static" directory relative to the location of the FastAPI script or application.
  • name="static": An optional name that can be given to the mounted static files. It is used to reference the mounted files elsewhere in the application if needed.

With this code, any files placed in the “static” directory will be accessible via the /static URL path. For example, if we have a file named "dog1.jpg" in the "static" directory, it can be accessed /static/dog1.jpg in the browser. The entire code after mounting the folder static is given below.

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
import uvicorn

from fastapi.staticfiles import StaticFiles

app = FastAPI()

templates = Jinja2Templates(directory="templates")

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get('/')
def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})


if __name__ == "__main__":

uvicorn.run(
"app:app",
host = "0.0.0.0",
port = 8036,
reload = True
)

Let's check if this is working. I have to use the following URL to view the dog2 image.

http://0.0.0.0:8036/static/dog2.jpg

To access them in our HTML file,

<img src="{{ url_for('static', path='path_to_image.jpg') }}" class="img-fluid" alt="alternate-name">

In this example, the img tag is set to display an image with the path 'path_to_image.jpg'. You can replace 'path_to_image.jpg' with the actual path of the image file, you want to display. Additionally, you can set the class attribute to "img-fluid" responsive image behavior and set the alt attribute to the desired alternate name or description for accessibility purposes. The entire code of index.html,

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<title>Image Gallery</title>
</head>
<body>
<div class="container mt-5">
<h1 class="text-center mb-5">Image Gallery</h1>
<div class="row">
{% for image_number in range(1, 11) %}
<div class="col-md-4">
<img src="{{ url_for('static', path='dog' ~ image_number ~ '.jpg') }}" class="img-fluid" alt="Dog {{ image_number }}">
</div>
{% endfor %}
</div>
</div>
</body>
</html>

Here, the index.html file is modified to use Jinja2 templating syntax and access the static images:

The {% for %} the loop is used to iterate over the numbers 1 to 10 using the range(1, 11) function to retrieve our dog1,dog2 … dog10.jpg. Inside the loop, the img tag uses the url_for function to generate the URL for each static image. The image source is constructed by concatenating the string, the current, and the file extension '.jpg'. During 1st iteration, the image tag will look like the following to render the dog1 image.

<img src="{{ url_for('static', path='dog1.jpg') }}" class="img-fluid" alt="Dog {{ image_number }}">

In the code snippet above, the ~ the operator is used to concatenating the strings 'dog', the image_number variable, and '.jpg' to form the complete path of the image. The resulting path will be something like 'dog1.jpg', 'dog2.jpg', and so on.

Now let's run the code.

Now, when I access the FastAPI application at http://localhost:8036/, the index.html the template is rendered, and the images "dog1.jpg" to "dog10.jpg" are displayed in a grid layout on the webpage.

GitHub repository for this app:

https://github.com/SarumathyPrabakaran/image-gallery

Hope it helps.

--

--