Framework Integrations

Jinja2 Fragments provides seamless integration with popular Python web frameworks. Each framework integration is designed to align with that framework’s specific patterns and idioms for template rendering.

The installation of Jinja2 Fragments for all them is the same:

pip install jinja2-fragments

Flask Integration

Jinja2 Fragments provides a Flask-specific render_block function that works as a drop-in replacement for Flask’s built-in render_template.

To use Jinja2 Fragments with Flask, import render_block from the jinja2_fragments.flask module:

from flask import Flask, render_template
from jinja2_fragments.flask import render_block

app = Flask(__name__)


@app.get("/full_page")
def full_page():
    return render_template("page.html.jinja2", magic_number=42)


@app.get("/only_content")
def only_content():
    return render_block("page.html.jinja2", "content", magic_number=42)

The render_block function has the same signature as Flask’s render_template, with an additional parameter for the block name:

render_block(template_name_or_list, block_name, **context)

You can also use the render_blocks function (plural) to render multiple blocks at once:

from jinja2_fragments.flask import render_blocks


@app.get("/multiple_blocks")
def multiple_blocks():
    return render_blocks("page.html.jinja2", ["header", "content"], magic_number=42)

This is useful for htmx out-of-band updates where you need to update multiple elements in a single request.

Quart Integration

The Jinja2 Fragments integration with Quart is very similar to Flask but designed for async usage.

To use Jinja2 Fragments with Quart, import render_block from the jinja2_fragments.quart module:

from quart import Quart, render_template
from jinja2_fragments.quart import render_block

app = Quart(__name__)


@app.get("/full_page")
async def full_page():
    return await render_template("page.html.jinja2", magic_number=42)


@app.get("/only_content")
async def only_content():
    return await render_block("page.html.jinja2", "content", magic_number=42)

Note

Note that both functions are asynchronous and need to be awaited, following Quart’s async-first design philosophy.

The render_block function has the same signature as Quart’s render_template, with an additional parameter for the block name:

await render_block(template_name_or_list, block_name, **context)

Multiple blocks can be rendered with the render_blocks function, similar to the Flask integration.

Starlette Integration

Jinja2 Fragments provides native support for Starlette through the Jinja2Blocks class that extends Starlette’s Jinja2Templates. Since FastAPI is built on top of Starlette, this integration works with both pure Starlette applications and FastAPI applications.

To use Jinja2 Fragments with Starlette, import Jinja2Blocks from the jinja2_fragments.starlette module:

from starlette.applications import Starlette
from starlette.requests import Request
from starlette.routing import Route
from jinja2_fragments.starlette import Jinja2Blocks

templates = Jinja2Blocks(directory="path/to/templates")


async def full_page(request: Request):
    return templates.TemplateResponse(request, "page.html.jinja2", {"magic_number": 42})


async def only_content(request: Request):
    return templates.TemplateResponse(
        request, "page.html.jinja2", {"magic_number": 42}, block_name="content"
    )


routes = [
    Route("/full_page", full_page),
    Route("/only_content", only_content),
]

app = Starlette(routes=routes)

The Jinja2Blocks class works exactly like Starlette’s Jinja2Templates, but allows you to include an optional block_name parameter to the TemplateResponse method.

Note

You can also render multiple blocks at once by using the block_names parameter with a list of block names.

FastAPI Integration

Jinja2 Fragments provides seamless FastAPI integration. Since FastAPI uses Starlette under the hood, the FastAPI integration is built on top of the Starlette implementation.

To use Jinja2 Fragments with FastAPI, import Jinja2Blocks from the jinja2_fragments.fastapi module:

from fastapi import FastAPI
from fastapi.requests import Request
from jinja2_fragments.fastapi import Jinja2Blocks

app = FastAPI()

templates = Jinja2Blocks(directory="path/to/templates")


@app.get("/full_page")
async def full_page(request: Request):
    return templates.TemplateResponse(request, "page.html.jinja2", {"magic_number": 42})


@app.get("/only_content")
async def only_content(request: Request):
    return templates.TemplateResponse(
        request, "page.html.jinja2", {"magic_number": 42}, block_name="content"
    )

The Jinja2Blocks class works exactly like FastAPI’s Jinja2Templates, but allows you to include an optional block_name parameter to the TemplateResponse method.

Important

Remember that FastAPI’s template system requires a request object in the context, as shown in the examples above.

Sanic Integration

Jinja2 Fragments provides a replacement for Sanic’s template rendering function.

To use Jinja2 Fragments with Sanic, import render from the jinja2_fragments.sanic module:

from sanic import Sanic, Request
import sanic_ext
from jinja2_fragments.sanic import render

app = Sanic(__name__)
app.extend(config=sanic_ext.Config(templating_path_to_templates="path/to/templates"))


@app.get("/full_page")
async def full_page(request: Request):
    return await render("page.html.jinja2", context={"magic_number": 42})


@app.get("/only_content")
async def only_content(request: Request):
    return await render(
        "page.html.jinja2", block="content", context={"magic_number": 42}
    )

The render function is a drop-in replacement for Sanic’s template extension’s render(). Your request context and environment configuration will work the same as before.

Note

By default, the full page is rendered (block=None) unless you provide a block keyword argument.

Litestar Integration

Jinja2 Fragments provides integration with Litestar through the HTMXBlockTemplate class.

To use Jinja2 Fragments with Litestar, import HTMXBlockTemplate from the jinja2_fragments.litestar module:

Important

HTMXBlockTemplate can be used as a drop-in replacement for Litestar’s Template class. However, passing multiple positional arguments to HTMXBlockTemplate is deprecated and will be removed in a future version. Use template_name as the only positional argument and pass all other parameters as keyword arguments.

Recommended usage: HTMXBlockTemplate("template.html", block_name="content", push_url="/url")

Deprecated usage: HTMXBlockTemplate("/url", "innerHTML", "#target", template_name="template.html")

try:
    # litestar>=2.13.0
    from litestar.plugins.htmx import HTMXRequest
except ImportError:
    # litestar<2.13.0
    from litestar.contrib.htmx.request import HTMXRequest

from litestar import get, Litestar
from litestar.response import Template

from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.template.config import TemplateConfig
from jinja2_fragments.litestar import HTMXBlockTemplate


@get("/full_page")
def full_page(request: HTMXRequest) -> Template:
    return HTMXBlockTemplate(
        template_name="page.html.jinja2", context={"magic_number": 42}
    )


@get("/only_content")
def only_content(request: HTMXRequest) -> Template:
    return HTMXBlockTemplate(
        template_name="page.html.jinja2",
        block_name="content",
        context={"magic_number": 42},
    )


app = Litestar(
    route_handlers=[full_page, only_content],
    request_class=HTMXRequest,
    template_config=TemplateConfig(
        directory="path/to/templates",
        engine=JinjaTemplateEngine,
    ),
)

Note

By default, the full page is rendered unless you provide a block_name keyword argument.