jinja2-fragments

repository·main·Indexed 18 days ago

https://github.com/sponsfreixes/jinja2-fragments

A Python library for rendering specific named blocks from Jinja2 templates as standalone HTML fragments. It supports the 'Template Fragments' pattern, ideal for HTMX-based applications requiring partial HTML updates without splitting templates into multiple files. Provides integrations for FastAPI, Starlette, Litestar, Flask, Quart, and Sanic, as well as core functions like render_block and render_blocks for single or multiple block rendering.

Tokens
12.3K
Snippets
46
Records
63
Agent score
61%

What's inside jinja2-fragments

  1. How Jinja2 Fragments works

    main

    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.

    Instead of splitting blocks into separate files and using include tags, you define all blocks in one template file. You can then choose to render the full template or render specific blocks independently. This is particularly useful for libraries like htmx that require fetching partial HTML content.

  2. Set up the development environment

    main

    To contribute to jinja2-fragments, you need Python 3.9+, pip, and git. Follow these steps to clone the repository, set up a virtual environment, and install the package in editable mode with all necessary development, test, and documentation dependencies.

    1. Clone the repository.
    2. Create and activate a virtual environment.
    3. Install the package in development mode using pip install -e ".[dev,tests,docs]".
    4. Install pre-commit hooks.
    # Clone the repository
    git clone https://github.com/sponsfreixes/jinja2-fragments
    cd jinja2-fragments
    
    # Create and activate a virtual environment
    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    
    # Install the package in development mode with all dependencies
    pip install -e ".[dev,tests,docs]"
    
    # Install pre-commit hooks
    pre-commit install
  3. Integrate Jinja2 Fragments with Flask

    main

    Use render_block as a drop-in replacement for Flask's render_template to render specific blocks. You can also use render_blocks (plural) to render multiple blocks at once, which is useful for htmx out-of-band updates.

    Import from jinja2_fragments.flask.

    from flask import Flask, render_template
    from jinja2_fragments.flask import render_block, render_blocks
    
    app = Flask(__name__)
    
    @app.get("/full_page")
    def full_page():
        # Renders the whole template
        return render_template("page.html.jinja2", magic_number=42)
    
    @app.get("/only_content")
    def only_content():
        # Renders only the 'content' block
        return render_block("page.html.jinja2", "content", magic_number=42)
    
    @app.get("/multiple_blocks")
    def multiple_blocks():
        # Renders multiple blocks at once
        return render_blocks("page.html.jinja2", ["header", "content"], magic_number=42)
  4. Use jinja2-fragments with FastAPI

    main

    Use the Jinja2Blocks wrapper from jinja2_fragments.fastapi. It extends FastAPI's Jinja2Templates and allows an optional block_name parameter in TemplateResponse.

    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):
        # Renders only the 'content' block
        return templates.TemplateResponse(
            request, "page.html.jinja2", {"magic_number": 42}, block_name="content"
        )
  5. Use jinja2-fragments with Starlette

    main

    Use the Jinja2Blocks class from jinja2_fragments.starlette, which extends Starlette's Jinja2Templates. Pass block_name to TemplateResponse to render a specific block.

    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):
        # Renders only the 'content' block
        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)