FastAPI - Templates



By default, FastAPI renders a JSON response to the client. However, it can be cast to a HTML response. For this purpose, FastAPI has HTMLResponse class defined in fastapi.responses module. We need to add response_class as an additional parameter to operation decorator, with HTMLResponse object as its value.

In the following example, the @app.get() decorator has "/hello/" endpoint and the HTMLResponse as response_class. Inside the hello() function, we have a string representation of a HTML code of Hello World message. The string is returned in the form of HTML response.

from fastapi.responses import HTMLResponse
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello/")
async def hello():
   ret='''
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
'''
   return HTMLResponse(content=ret)

On examining the API docs, it can be seen that the server’s response body is in HTML.

FastAPI Templates

The request URL (http://localhost:8000/hello/) should also render the message in the browser. However, rendering a raw HTML response is very tedious. Alternately, it is possible to render prebuilt HTML pages as templates. For that we need to use a web template library.

Web template library has a template engine that merges a static web page having place holder variables. Data from any source such as database is merged to dynamically generate and render the web page. FastAPI doesn’t have any prepackaged template library. So one is free to use any one that suits his needs. In this tutorial, we shall be using jinja2, a very popular web template library. Let us install it first using pip installer.

pip3 install jinja2

FastAPI’s support for Jinja templates comes in the form of jinja2Templates class defined in fastapi.templates module.

from fastapi.templating import Jinja2Templates

To declare a template object, the folder in which the html templates are stored, should be provided as parameter. Inside the current working directory, we shall create a ‘templates’ directory.

templates = Jinja2Templates(directory="templates")

A simple web page ‘hello.html’ to render Hello World message is also put in ‘templates’ folder.

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

We are now going to render html code from this page as HTMLResponse. Let us modify the hello() function as follows −

from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import FastAPI, Request
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/hello/", response_class=HTMLResponse)
async def hello(request: Request):
   return templates.TemplateResponse("hello.html", {"request": request})

Here, templateResponse() method of template object collects the template code and the request context to render the http response. When we start the server and visit the http://localhost:8000/hello/ URL, we get to see the Hello World message in the browser, which is in fact the output of hello.html

FastAPI Templates

As mentioned earlier, jinja2 template allows certain place holders to be embedded in the HTML code. The jinja2 code elements are put inside the curly brackets. As soon as the HTML parser of the browser encounters this, the template engine takes over and populates these code elements by the variable data provided by the HTTP response. Jinja2 provides following code elements −

  • {% %} – Statements

  • {{ }} – Expressions to print to the template output

  • {# #} − Comments which are not included in the template output

  • # # # − Line statements

The hello.html is modified as below to display a dynamic message by substituting the name parameter.

<html>
<body>
<h2>Hello {{name}} Welcome to FastAPI</h2>
</body>
</html>

The operation function hello() is also modified to accept name as a path parameter. The TemplateResponse should also include the JSON representation of “name”:name along with the request context.

from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi import FastAPI, Request
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/hello/{name}", response_class=HTMLResponse)
async def hello(request: Request, name:str):
   return templates.TemplateResponse("hello.html", {"request": request, "name":name})

Restart the server and go to http://localhost:8000/hello/Kiran. The browser now fills the jinja2 place holder with the path parameter in this URL.

FastAPI Templates
Advertisements