Rendering HTML Template with FastAPI x Jinja

2 min read

Time to build something exciting! We're creating a blog system using FastAPI with proper template rendering. Let's dive into the structure and see how everything connects.

🌳 C:\Users\soura\Documents\mine\fastapi\blog
├── 📁 alembic
|  ├── 📄 env.py
├── 📄 alembic.ini
├── 📁 apis
├── 📁 apps   #new
|  ├── 📄 main.py
|  └── 📁 v1
|     └── 📄 blog.py 
├── 📁 core
|  ├── 📄 config.py
|  └── 📄 security.py
├── 📁 database
|  ├── 📁 crud
|  |  ├── 📄 blog.py
|  |  └── 📄 user.py
|  ├── 📄 db.py
|  └── 📁 models
|     ├── 📄 base.py
|     ├── 📄 blog.py
|     ├── 📄 user.py
|     └── 📄 __init__.py
├── 📄 docker-compose.yaml
├── 📄 Dockerfile
├── 📄 main.py
├── 📄 requirements.txt
├── 📁 schemas
|  ├── 📄 blog.py
|  ├── 📄 user.py
|  └── 📁 __pycache__
|     └── 📄 user.cpython-311.pyc
└── 📁 templates  #new
   └── 📁 blog
      └── 📄 list.html

Setting Up Dependencies

First things first, let's get our requirements sorted. Create a requirements.txt file and add jinja in the dependency:

fastapi==0.115.12
uvicorn==0.27.1
python-dotenv==1.1.1
psycopg2-binary==2.9.10
sqlmodel==0.0.24
alembic==1.16.4
PyJWT==2.10.1
python-multipart==0.0.20
#new
Jinja2==3.1.6

The new addition here is Jinja2==3.1.6 - our templating engine that'll help us serve beautiful HTML pages instead of just JSON responses.

Let's start with the blog functionality. In apps/v1/blog.py:

from fastapi import APIRouter
from fastapi import Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates


templates = Jinja2Templates(directory="templates")
router = APIRouter()


@router.get("/", response_class=HTMLResponse)
def get_blogs(request: Request):
    return templates.TemplateResponse("blog/list.html", {"request": request})

Notice we're using response_class=HTMLResponse. This tells FastAPI we're returning HTML, not JSON. The async keyword isn't strictly necessary for this simple function, but it's good practice.

Breaking this down:

  • We create a templates object pointing to our templates directory
  • router = APIRouter() gives us a clean way to organize our routes
  • The get_blogs function uses HTMLResponse instead of the default JSON response
  • templates.TemplateResponse renders our HTML template with the request context

The key insight here? Always pass the request object in the context dictionary. Templates need access to request data for things like URL generation, user information, and more.

App-Level Routing Structure

Our routing follows a clean, organized pattern. Create a apps/main.py file:

from fastapi import APIRouter
from apps.v1.blog import router as blog_router


app_router = APIRouter()

app_router.include_router(blog_router, prefix="/blogs", tags=["blogs app"])

The main.py at root ties everything together. 

from fastapi import FastAPI
#...
from apis.main import api_router
from apps.main import app_router

app: FastAPI = FastAPI(title=settings.TITLE, description=settings.DESCRIPTION, version=settings.VERSION)
app.include_router(api_router)
app.include_router(app_router)

HTML Template with Modern Styling

Let's create templates/blog/list.html. Our blog list template uses Tailwind CSS via CDN. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
    <title>Blog List</title>
</head>
<body>
    <h1 class="text-3xl font-bold text-center">Blog List</h1>
</body>
</html>

Using Tailwind's browser version is perfect for rapid prototyping. The text-3xl font-bold text-center classes give us a clean, centered heading without writing custom CSS.

 

FastAPITutorial

My priority is to help build a production-ready application using FastAPI

I prioritize quality over simplicity. Our challenging approach ensures you're prepared for real-world development.

Contacts

Refunds:

Refund Policy
Social

Follow us on our social media channels to stay updated with our latest tutorials and resources.

© Copyright 2022-2025 Team FastAPITutorial. All rights reserved.