Sling Academy
Home/FastAPI/FastAPI: How to use macros in Jinja templates

FastAPI: How to use macros in Jinja templates

Last updated: February 06, 2024

Introduction

When building web applications with FastAPI, it’s often necessary to generate HTML dynamically. The Jinja2 template engine, which integrates seamlessly with FastAPI, provides a powerful yet straightforward syntax for creating dynamic web content. One of Jinja’s lesser-known but incredibly useful features is macros. Macros are akin to functions in programming languages, allowing for reusable template fragments. This tutorial will guide you through using macros in Jinja templates within a FastAPI application to create more maintainable and reusable code.

Getting Started with FastAPI and Jinja

First, ensure you have FastAPI and Jinja2 installed in your Python environment:

pip install fastapi jinja2 uvicorn

Create a basic FastAPI app:

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory='templates')

@app.get('/', response_class=HTMLResponse)
async def read_root(request: Request):
    return templates.TemplateResponse('index.html', {'request': request})

The above code sets up a simple FastAPI application and configures Jinja2 for template rendering, pointing it to a ‘templates’ directory.

Introduction to Jinja Macros

Macros in Jinja templates allow you to define reusable chunks of template code. Here’s a basic example:

{% macro input(name, value='', type='text') %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

This macro generates an HTML input element. To use this macro in your templates, you should first import it:

{% import 'forms.html' as forms %}

Then, you can use your defined macro like so:

{{ forms.input('username') }}
{{ forms.input('password', type='password') }}

Passing Parameters to Macros

Macros can accept parameters to make them more dynamic. Here’s an example where we add an ‘id’ parameter to our input macro:

{% macro input(name, value='', type='text', id=None) %}
<input type="{{ type }}" id="{{ id }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

Such flexibility allows for more dynamic and reusable templates, reducing code redundancy and increasing maintainability.

Using Macros Across Multiple Templates

A common use case for macros is reusing them across multiple templates. To facilitate this, place macros in separate files, and import them into your templates as needed. Here’s how you might organize your template directory:

  • templates/
  • — forms.html (contains macros)
  • — index.html
  • — login.html

Then, in ‘index.html’ or ‘login.html’, you can import the macros from ‘forms.html’ and use them:

{% import 'forms.html' as forms %}
{{ forms.input('email') }}

Advanced Macro Techniques

Macros can also include other macros or even call themselves recursively. For complex UI components that are reused throughout an application, macros can significantly simplify template code.

Moreover, you can pass entire blocks of content to a macro using the ‘caller’ functionality. This advanced technique allows you to wrap content in a predefined template structure, enabling even more flexibility:

{% macro panel(title, class='panel') %}
<div class="{{ class }}">
  <h2>{{ title }}</h2>
  {% block content %}{% endblock %}
</div>
{% endmacro %}

{% call(panel, title='My Panel') %}
{% block content %}
  <p>This is a panel content.</p>
{% endblock %}
{% endcall %}

This tutorial has provided an introduction to utilizing macros in Jinja templates within your FastAPI applications. Leveraging macros can result in cleaner, more maintainable, and reusable template code, enhancing your development workflow and productivity.

By streamlining your use of templates and investing time in creating reusable components, you can build complex web applications more efficiently. As you grow more comfortable with FastAPI and Jinja, exploring further into their advanced features will uncover even more powerful techniques to supercharge your web development projects.

Next Article: Deploying FastAPI on Ubuntu with Nginx and Let’s Encrypt

Previous Article: FastAPI: How to Create a Custom 404 (Not Found) Route

Series: FastAPI Tutorials for Beginners

FastAPI

You May Also Like

  • Popular useful built-in Jinja filters you should know
  • How to remove consecutive whitespace in rendered Jinja pages
  • How to format large numbers with thousand separators in Jinja template
  • How to format date time in Jinja templates
  • FastAPI + Jinja: How to create custom filters
  • How to pass variables from Python (FastAPI) to Jinja
  • How to decode Jinja response to string
  • How to create and use macros in Jinja
  • How to use namespace in Jinja
  • How to use if/ else in Jinja
  • How to use loops in Jinja
  • FastAPI + SQLAlchemy: Using cursor-based pagination
  • Fixing Common Swagger UI Errors in FastAPI
  • FastAPI Error: 307 Temporary Redirect – Causes and Solutions
  • FastAPI Error: Expected UploadFile, received ‘str’
  • Resolving FastAPI ImportError: No Known Parent Package
  • FastAPI Error: No module named ‘pydantic_core._pydantic_core’
  • Resolving FastAPI 422 Error: Value is not a valid dict
  • Resolving the FastAPI Circular References Error