I have a habit of developing monolithic web apps for a long time. So, if I don't see anything on the UI, it doesn't look good to me. So, what I am going to do next is to implement a navbar and a simple message on our homepage. I know FastAPI follows API first approach but it can also serve webapps. The other thing is if someone hits our home/index endpoint they won't understand anything because we are not rendering any webpage . So, a template is necessary.
We will be using Jinja as our templating language. Before that, we need to make some folders and files. Notice the below folder structure of mine, the names 'apis/', 'templates/' are ending with a '/', so these are folders and others are simple .py or .html files. I have added a comment '#new' for the new files and folders that need to be created.
learning_fastapi/
├─.gitignore
└─backend/
├─apis/ #new
│ └─general_pages/ #new
│ └─route_homepage.py #new
├─core/
│ └─config.py
├─main.py
├─requirements.txt
└─templates/ #new
├─components/ #new
│ └─navbar.html #new
├─general_pages/ #new
│ └─homepage.html #new
└─shared/ #new
└─base.html #new
Now, enter the below lines in 'route_homepage.py'.
#route_homepage.py
from fastapi import APIRouter
from fastapi import Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")
general_pages_router = APIRouter()
@general_pages_router.get("/")
async def home(request: Request):
return templates.TemplateResponse("general_pages/homepage.html",{"request":request})
Next, we need to concentrate on homepage.html. Copy the below code in this file.
{% extends "shared/base.html" %}
{% block title %}
<title>Job Board</title>
{% endblock %}
{% block content %}
<div class="container">
<h1 class="display-4">Find Jobs...</h1>
</div>
{% endblock %}
This is our base.html file.
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="nofoobar.com" content="Nofoobar">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
{% block title %}
{% endblock %}
</head>
<body>
{% block content %}
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
{% block scripts %}
{% endblock %}
</body>
</html>
Done? No! there are still some things left. One is our main.py file has app, which does not know about all of these. So, we are going to inform our main.py file to include this general_pages_router.
#main.py
from fastapi import FastAPI
from core.config import settings
from apis.general_pages.route_homepage import general_pages_router
def include_router(app):
app.include_router(general_pages_router)
def start_application():
app = FastAPI(title=settings.PROJECT_NAME,version=settings.PROJECT_VERSION)
include_router(app)
return app
app = start_application()
# @app.get("/") #remove this, It is no longer needed.
# def hello_api():
# return {"msg":"Hello API"}
Ok, one last thing, I promise last. We don't have Jinja2, So, add the below line in requirements.txt:
fastapi
uvicorn
#for template #new
jinja2
Now, install Jinja2 like with pip install -r requirements.txt. All done, not start the server with uvicorn main:app --reload and visit http://127.0.0.1:8000/. You should see a template response as:
Thats all for this post, It has already become little big! I will continue to add navbar in next post.
Final git commit : Add support for template response in homepage · nofoobar/JobBoard-Fastapi@e5450e9 (github.com)