Skip to content

FastAPI Web Application with Dynamic HTML Templates

Are you interested in web application development using Python? If so, you've come to the right place! In this article, we'll explore how to build a web application using FastAPI, a modern and efficient web framework. By the end of this article, you will have a basic understanding of how to create a web application with FastAPI and render dynamic HTML templates.

Getting Started To begin, let's set up our development environment. Make sure you have Python installed on your machine. If not, you can download it from the official Python website. Once Python is installed, we can proceed with building our FastAPI application. You can read how to setup project in this article.

Project Files and Folders Structure

├── main.py
├── static
   └── css
       └── style.css
└── templates
    ├── core.html
    └── index.html
  • First, let's import the necessary modules and libraries:
import pathlib
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
  • Next, we'll create our FastAPI application instance:
app = FastAPI()
  • We also need to define the base directory and set up the templates directory for our application:
BASE_DIR = pathlib.Path(__file__).parent
templates = Jinja2Templates(directory=[
    BASE_DIR / "templates",
])
  • To serve static files like CSS or JavaScript, we'll mount a static directory:
app.mount("/static", StaticFiles(directory="static"), name="static")
  • Now that we have our basic setup in place, let's move on to creating a simple route that will render our home page.
@app.get('/', response_class=HTMLResponse)
async def index(request: Request):
    posts = [
        {"id":1, "title":"fastapi.blog title 1", "body":"Learn FastAPI with the fastapi.blog team 1"},
        {"id":2, "title":"fastapi.blog title 2", "body":"Learn FastAPI with the fastapi.blog team 2"},
        {"id":3, "title":"fastapi.blog title 3", "body":"Learn FastAPI with the fastapi.blog team 3"},
    ]
    context = {
        "request": request,
        "posts": posts,
        "title": "Home Page"
    }
    response = templates.TemplateResponse("index.html", context)
    return response
  • In this code snippet, we define a route using the @app.get decorator that listens for HTTP GET requests to the root URL (/). The response_class=HTMLResponse parameter indicates that we want to return an HTML response.

  • Inside the index function, we create a list of dummy blog post data. We then define a context dictionary that contains the request object, the list of posts, and the title of the page. Finally, we use the TemplateResponse class to render the index.html template with the provided context and return the response.

core.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
    <!-- project CSS -->
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <div class="container">
        <!-- HEADER -->
        {% block core_header%}
        <h1>header</h1>
        {% endblock core_header%}
        <hr>
        <br>
        <!-- BODY -->
        {% block core_body%}
        <h1>body</h1>
        {% endblock core_body%}
        <hr>
        <br>
        <!-- FOOTER -->
        {% block core_footer%}
        <h1>footer</h1>
        {% endblock core_footer%}
    </div>
</body>
</html>
  • This template serves as the core structure for all the pages in the web application. It defines the basic HTML structure and includes placeholders for the title, CSS, header, body, and footer.

  • {{title}}: This is a placeholder that will be replaced with the actual title of the page. : This line links the CSS file style.css located in the /static/css directory.

  • Within the body of the template:
    • {% block core_header%}...{% endblock core_header%}: This defines a block named core_header where specific content for the header can be inserted. This content will vary depending on the page that extends this template.
    • {% block core_body%}...{% endblock core_body%}: This block is for the main content of the page. Similar to the header block, it can be overridden and customized in the child templates.
    • {% block core_footer%}...{% endblock core_footer%}: This block is for the footer of the page, allowing customization in child templates.

index.html

{% extends 'core.html' %}
{% block core_body%}
<div class="index">
    <h1>Hello from index page!</h1>
        {% if posts %}
        {% for post in posts %}
        <div class="card">
            <div>
                <a href="#">{{post.id}}</a>
                <b>{{post.title}}</b>
            </div>
            <small>{{post.body}}</small>
        </div>
        {% endfor %}
        {% endif %}
</div>
{% endblock core_body%}
  • This template extends the core.html template and provides specific content for the core_body block.

  • {% extends 'core.html' %}: This line specifies that the index.html template extends the core.html template, inheriting its structure and blocks. {% block core_body%}...{% endblock core_body%}: This block overrides the core_body block from the core.html template, allowing the insertion of unique content for the index page.

  • {% if posts %}...{% endif %}: This conditional statement checks if there are any posts to display. If there are, it enters the loop to iterate over each post.
  • {% for post in posts %}...{% endfor %}: This loop iterates over the posts list and dynamically generates HTML content for each post using the provided data.
  • {{post.id}}, {{post.title}}, {{post.body}}: These are placeholders that will be replaced with the actual values of the corresponding properties for each post.

style.css

body{
    background-color: rgb(255, 255, 200);
}
h1{
    text-align: center;
}
.container{
    margin-left: auto;
    margin-right: auto;
    max-width: 60%;
    background-color: white;
    box-shadow: 5px 5px 5px #ccc;
}
.index{
    min-height: 400px;
}
.card{
    display: block;
    background-color: white;
    box-shadow: 5px 5px 5px #ccc;
    max-width: 18rem;
    max-height: 18rem;
    margin-left: auto;
    margin-right: auto;
    padding: 3px;
    margin-bottom: 5px;
}
.card a{
    text-decoration: none;
    padding: 2px;
    background-color: teal;
    color: white;
    font-size: 36px;
}
.card small{
    margin-top: auto;
}
  • That's it! We've successfully created a basic FastAPI application that renders a home page with dynamic content.

Conclusion

  • Congratulations on completing this beginner's guide to building a web application with FastAPI! We've covered the essential steps, from setting up the development environment to creating a basic route that renders a dynamic HTML page. With this foundation, you can continue exploring FastAPI and build more complex and feature-rich web applications.

  • Keep practicing and experimenting with FastAPI, and you'll soon become proficient in web application development using this powerful framework. Happy coding!