Git commit: render HTML with Jinja Templates
If we are serving the content only in the form of an API, Then only the developers would be able to consume the content. Our blog should be readable by any layman without much effort. To enable this, we will have to serve HTML based response.
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.
backend/
├─.env
├─.env.example
├─alembic/
├─alembic.ini
├─apis/
│ ├─base.py
│ ├─v1/
│ │ ├─route_blog.py
│ │ ├─route_login.py
│ │ ├─route_user.py
├─apps/
│ ├─base.py #new
│ ├─v1/ #new
│ ├─route_blog.py #new
├─core/
│ ├─config.py
│ ├─hashing.py
│ ├─security.py
├─db/
├─main.py
├─requirements.txt
├─schemas/
├─templates/
│ ├─base.html #new
│ └─blog/ #new
│ └─home.html #new
├─tests/
├─test_db.db
Now, enter the below lines in apps > v1 > route_blog.py
from fastapi import APIRouter
from fastapi import Request
from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")
router = APIRouter()
@router.get("/")
def home(request: Request):
return templates.TemplateResponse("blog/home.html", {"request": request})
print(dir(request)) ,
we see that request has many important attributes like 'user','cookies', 'form', 'get', 'headers', 'path_params', 'query_params', ' 'url','url_for',
'values'
which might be used in templates. e.g. It is very common to use request.user in the template file.Next, we need to concentrate on templates> blog > home.html. Copy the below code in this file.
{% extends "base.html" %}
{% block title %}
<title>Algoholic</title>
{% endblock %}
{% block content %}
<div class="container">
<h1 class="display-4">All Blogs</h1>
</div>
{% endblock %}
This is our base.html file.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block title %}
{% endblock %}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
{% block content %}
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" 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 router. Let's use the same pattern of keeping a base.py file that will have all the routers of apps/.
from apps.v1 import route_blog
from fastapi import APIRouter
app_router = APIRouter()
app_router.include_router(
route_blog.router, prefix="", tags=[""], include_in_schema=False
)
Finally, we are going to include the common api_router in the main.py file.
from apis.base import api_router
from apps.base import app_router #new
###
def include_router(app):
app.include_router(api_router)
app.include_router(app_router) #new
Ok, one last thing, I promise last. We don't have Jinja2, So, add the below line in requirements.txt:
Jinja2==3.1.2
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:
That's all for this post, It has already become a little big! I will continue to add the navbar in the next post.
Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.
We know, we might make it hard for you but definitely worth the efforts.
© Copyright 2022-23 Team FastAPITutorial