FastAPI & Templates: Build Dynamic Web Apps
FastAPI & Templates: Build Dynamic Web Apps
Hey guys! Ever wondered how to make your FastAPI application a bit more dynamic and visually appealing? Well, you’re in the right place! In this article, we’ll dive deep into using templates with FastAPI to render dynamic web pages. Forget about just serving JSON; let’s create full-fledged web applications that can display data in a user-friendly format. We’ll cover everything from setting up the environment to rendering your first template, passing data, and even handling more complex scenarios. So, buckle up, and let’s get started!
Table of Contents
Setting Up Your Environment
Before we jump into the code, let’s get our environment ready. First, make sure you have Python installed. I recommend using Python 3.7 or higher. Once you have Python, you’ll need to install FastAPI and Jinja2, which is a popular templating engine that we’ll be using. You can install these using pip, the Python package installer. Just open your terminal or command prompt and run the following command:
pip install fastapi Jinja2 uvicorn
FastAPI
is our web framework,
Jinja2
is for templating, and
Uvicorn
is an ASGI server that will run our application. After installing these packages, create a new directory for your project. Inside this directory, create a file named
main.py
. This will be the main file for our FastAPI application. Also, create a directory named
templates
. This is where we’ll store our HTML templates. Your project structure should look something like this:
myproject/
├── main.py
└── templates/
Now that we have our environment set up, we can start writing some code. Open
main.py
in your favorite text editor or IDE, and let’s start building our FastAPI application.
Creating Your First FastAPI Application
Let’s start with a basic FastAPI application. We’ll create a simple route that returns a string. This will help us ensure that FastAPI is working correctly before we move on to templates. Add the following code to your
main.py
file:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
This code creates a FastAPI application and defines a route for the root path (
/
). When you visit the root path in your browser, it will return a JSON response with the message
{"Hello": "World"}
. To run this application, open your terminal, navigate to your project directory, and run the following command:
uvicorn main:app --reload
This command starts the Uvicorn server, which will host our FastAPI application. The
--reload
flag tells Uvicorn to automatically restart the server whenever you make changes to your code. This is very useful during development. Now, open your web browser and go to
http://localhost:8000
. You should see the JSON response displayed in your browser. If you see this, congratulations! Your FastAPI application is working correctly.
Integrating Jinja2 Templates
Now that we have a basic FastAPI application running, let’s integrate Jinja2 templates. First, we need to configure Jinja2 to work with FastAPI. To do this, we’ll use the
Jinja2Templates
class from the
fastapi.templating
module. Add the following code to your
main.py
file:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/items/{id}", response_class=HTMLResponse)
async def read_item(request: Request, id: str):
return templates.TemplateResponse("item.html", {"request": request, "id": id})
In this code, we import the
Jinja2Templates
class and create an instance of it, passing the
templates
directory as the argument. This tells Jinja2 where to look for our templates. We also define a new route
/items/{id}
that takes an
id
as a path parameter. Inside the route, we use the
TemplateResponse
class to render the
item.html
template, passing a context dictionary containing the
request
object and the
id
parameter. Now, we need to create the
item.html
template. Create a new file named
item.html
inside the
templates
directory, and add the following code:
<!DOCTYPE html>
<html>
<head>
<title>Item</title>
</head>
<body>
<h1>Item ID: {{ id }}</h1>
</body>
</html>
This is a simple HTML template that displays the
id
parameter that we passed from the FastAPI route. The
{{ id }}
syntax is Jinja2’s way of embedding variables in the template. Now, restart your Uvicorn server and open your web browser. Go to
http://localhost:8000/items/123
. You should see the HTML template rendered in your browser, displaying the message
Item ID: 123
. If you see this, congratulations! You have successfully integrated Jinja2 templates with your FastAPI application. The
beauty of using templates
lies in the ability to separate the presentation layer from the application logic, making your code cleaner and more maintainable.
Passing Data to Templates
Passing data to templates is a crucial part of building dynamic web applications. We’ve already seen how to pass simple variables like the
id
parameter to the template. However, you can also pass more complex data structures, such as lists and dictionaries. Let’s modify our example to pass a list of items to the template. First, update your
main.py
file with the following code:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/items", response_class=HTMLResponse)
async def read_items(request: Request):
items = [{"name": "Item 1", "description": "This is item 1"},
{"name": "Item 2", "description": "This is item 2"},
{"name": "Item 3", "description": "This is item 3"}]
return templates.TemplateResponse("items.html", {"request": request, "items": items})
In this code, we define a new route
/items
that passes a list of items to the
items.html
template. Each item in the list is a dictionary with a
name
and a
description
. Now, create a new file named
items.html
inside the
templates
directory, and add the following code:
<!DOCTYPE html>
<html>
<head>
<title>Items</title>
</head>
<body>
<h1>Items</h1>
<ul>
{% for item in items %}
<li><strong>{{ item.name }}</strong>: {{ item.description }}</li>
{% endfor %}
</ul>
</body>
</html>
This template uses a
for
loop to iterate over the list of items and display each item’s name and description. The
{{ item.name }}
and
{{ item.description }}
syntax is used to access the values of the
name
and
description
keys in each item dictionary. Restart your Uvicorn server and open your web browser. Go to
http://localhost:8000/items
. You should see the list of items displayed in your browser. This demonstrates how you can pass complex data structures to your templates and use them to render dynamic content. Remember, the more dynamic your content, the more
engaging your web application
becomes!
Handling Forms
Handling forms is another common task in web development. FastAPI makes it easy to handle form data using request bodies. Let’s create a simple form that allows users to submit their name and email address. First, update your
main.py
file with the following code:
from fastapi import FastAPI, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/form", response_class=HTMLResponse)
async def read_form(request: Request):
return templates.TemplateResponse("form.html", {"request": request})
@app.post("/submit", response_class=HTMLResponse)
async def submit_form(request: Request, name: str = Form(...), email: str = Form(...)):
return templates.TemplateResponse("result.html", {"request": request, "name": name, "email": email})
In this code, we define two routes:
/form
and
/submit
. The
/form
route renders a form that allows users to enter their name and email address. The
/submit
route handles the form submission. We use the
Form
class to define the
name
and
email
parameters as form fields. The
...
argument indicates that these fields are required. Now, create a new file named
form.html
inside the
templates
directory, and add the following code:
<!DOCTYPE html>
<html>
<head>
<title>Form</title>
</head>
<body>
<h1>Form</h1>
<form action="/submit" method="post">
<label for="name">Name:</label><br>
<input type="text" id="name" name="name"><br><br>
<label for="email">Email:</label><br>
<input type="email" id="email" name="email"><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
This template defines a simple form with two fields:
name
and
email
. The
action
attribute of the form is set to
/submit
, which is the route that will handle the form submission. The
method
attribute is set to
post
, which indicates that the form data will be sent using the HTTP POST method. Finally, create a new file named
result.html
inside the
templates
directory, and add the following code:
<!DOCTYPE html>
<html>
<head>
<title>Result</title>
</head>
<body>
<h1>Result</h1>
<p>Name: {{ name }}</p>
<p>Email: {{ email }}</p>
</body>
</html>
This template displays the name and email address that were submitted through the form. Restart your Uvicorn server and open your web browser. Go to
http://localhost:8000/form
. You should see the form displayed in your browser. Enter your name and email address and click the Submit button. You should see the result page displaying the name and email address that you submitted. This demonstrates how you can handle forms in your FastAPI application using templates. This is a
powerful feature
that enables you to build interactive web applications.
Using Template Inheritance
Template inheritance is a powerful feature that allows you to reuse common parts of your templates, such as the header and footer. This can save you a lot of time and effort, and it can also make your templates more maintainable. Let’s create a base template that defines the basic structure of our web pages. Create a new file named
base.html
inside the
templates
directory, and add the following code:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<header>
<h1>My Website</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2023 My Website</p>
</footer>
</body>
</html>
This template defines the basic structure of our web pages, including the
<html>
,
<head>
,
<body>
,
<header>
,
<main>
, and
<footer>
elements. The
{% block title %}{% endblock %}
and
{% block content %}{% endblock %}
syntax defines blocks that can be overridden by child templates. Now, let’s create a child template that inherits from the base template. Create a new file named
home.html
inside the
templates
directory, and add the following code:
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to my website!</h1>
<p>This is the home page.</p>
{% endblock %}
This template inherits from the
base.html
template using the
{% extends "base.html" %}
syntax. It overrides the
title
and
content
blocks to provide the content for the home page. Now, update your
main.py
file with the following code:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("home.html", {"request": request})
In this code, we define a route for the root path (
/
) that renders the
home.html
template. Restart your Uvicorn server and open your web browser. Go to
http://localhost:8000
. You should see the home page displayed in your browser, with the header and footer from the base template and the title and content from the home template. This demonstrates how you can use template inheritance to reuse common parts of your templates. By
leveraging template inheritance
, you ensure consistency and reduce redundancy across your web application.
Conclusion
In this article, we’ve covered the basics of using templates with FastAPI to build dynamic web applications. We’ve seen how to set up the environment, create a basic FastAPI application, integrate Jinja2 templates, pass data to templates, handle forms, and use template inheritance. With these skills, you can start building more complex and engaging web applications with FastAPI. Remember, the key to building great web applications is to practice and experiment. So, go out there and start building! And don’t forget to have fun along the way. Happy coding, guys! Now you are able to use FastAPI templates .