Basic Usage =========== Jinja2 Fragments follows the principle of `Locality of Behavior `_ by allowing you to maintain a single template file for both full page and partial rendering. This eliminates the need to create separate template files for each block you want to render independently. Core Concepts ============= With traditional Jinja2, if you want to render a block by itself and as part of another page, you would typically: 1. Put that block in a separate file 2. Use the `include tag `_ or `Jinja Partials `_ on the wrapping template With Jinja2 Fragments, you can: 1. Define all blocks in a single template file 2. Render the full template when needed 3. Render specific blocks from that template when needed This approach is especially useful when working with htmx or similar libraries that fetch partial HTML content. Simple Block Rendering ====================== Let's start with a basic example using vanilla Jinja2. Consider the following template ``page.html.jinja2``: .. code-block:: html This is the title

This is a header

{% block content %}

This is the magic number: {{ magic_number }}.

{% endblock %} If you want to render only the ``content`` block, you can use ``render_block`` like this: .. code-block:: python from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2_fragments import render_block environment = Environment( loader=FileSystemLoader("my_templates"), autoescape=select_autoescape(("html", "jinja2")), ) rendered_html = render_block( environment, "page.html.jinja2", "content", magic_number=42 ) This will only render: .. code-block:: html

This is the magic number: 42.

.. note:: The ``render_block`` function takes the same arguments as Jinja2's ``render_template`` function, plus an additional argument for the block name to render. Multiple Blocks Rendering ========================= Jinja2 Fragments also allows you to render multiple blocks at once with the ``render_blocks`` function (notice the plural): .. code-block:: python from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2_fragments import render_blocks environment = Environment( loader=FileSystemLoader("my_templates"), autoescape=select_autoescape(("html", "jinja2")), ) rendered_html = render_blocks( environment, "page.html.jinja2", ["header", "content"], magic_number=42 ) .. note:: Rendering multiple blocks is particularly useful for implementing `out-of-band updates `_ when using htmx, allowing you to update multiple parts of a page in a single request. Rendering Blocks from Within Templates ====================================== You can also call ``render_block`` and ``render_blocks`` directly from within Jinja2 template expressions. This is useful when a template needs to compose fragments from other template files. To enable this, call :func:`~jinja2_fragments.setup_globals` on your Jinja2 environment: .. code-block:: python from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2_fragments import setup_globals environment = Environment( loader=FileSystemLoader("my_templates"), autoescape=select_autoescape(("html", "jinja2")), ) setup_globals(environment) Once installed, you can use ``render_block`` and ``render_blocks`` in any template rendered with that environment: .. code-block:: html
{{ render_block("customer/edit.html.jinja2", "customer", customer=invoice.customer) }}
{# Render multiple blocks at once #} {{ render_blocks("dashboard.html.jinja2", ["stats", "chart"], user=user) }} The current template context is automatically forwarded to the rendered block(s). Any keyword arguments you pass will override individual context variables. .. note:: ``setup_globals`` automatically selects the correct sync or async implementation based on ``environment.is_async``, so it works with both synchronous and asynchronous environments. Existing globals named ``render_block`` and ``render_blocks`` are preserved.