Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sponsfreixes/jinja2-fragments
Render Jinja2 template block as HTML page fragments on Python web frameworks.
https://github.com/sponsfreixes/jinja2-fragments
Last synced: 1 day ago
JSON representation
Render Jinja2 template block as HTML page fragments on Python web frameworks.
- Host: GitHub
- URL: https://github.com/sponsfreixes/jinja2-fragments
- Owner: sponsfreixes
- License: mit
- Created: 2022-09-05T05:41:21.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-28T23:57:44.000Z (9 months ago)
- Last Synced: 2024-05-19T17:50:44.298Z (8 months ago)
- Language: Python
- Size: 53.7 KB
- Stars: 183
- Watchers: 8
- Forks: 10
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- jimsghstars - sponsfreixes/jinja2-fragments - Render Jinja2 template block as HTML page fragments on Python web frameworks. (Python)
- awesome-python-htmx - Jinja2 fragments - FastAPI-a9bbcc?style=flat&logo=fastapi&logoColor=black" alt="FastAPI"></a> <a href="https://flask.palletsprojects.com/en" target="_blank"><img src="https://img.shields.io/badge/-Flask-a9bbcc?style=flat&logo=flask&logoColor=black" alt="Flask"></a> <a href="https://litestar.dev/" target="_blank"><img src="https://img.shields.io/badge/-Litestar-a9bbcc?style=flat&logoColor=black" alt="Litestar"></a> <a href="https://palletsprojects.com/p/jinja/" target="_blank"><img src="https://img.shields.io/badge/-Jinja2-a9bbcc?style=flat&logo=jinja&logoColor=black" alt="Jinja2"></a><br/> (Third Party Packages 📦 <a name = "tools"></a> / Helper Libraries)
README
# Jinja2 fragments
Jinja2 Fragments allows rendering individual blocks from
[Jinja2 templates](https://palletsprojects.com/p/jinja/). This library was created
to enable the pattern of
[Template Fragments](https://htmx.org/essays/template-fragments/) with Jinja2. It's a
great pattern if you are using [HTMX](https://htmx.org/) or some other library that
leverages fetching partial HTML.With jinja2, if you have a template block that you want to render by itself and
as part of another page, you are forced to put that block on a separate file and then
use the [include tag](https://jinja.palletsprojects.com/en/3.1.x/templates/#include)
(or [Jinja Partials](https://github.com/mikeckennedy/jinja_partials)) on the wrapping
template.With Jinja2 Fragments, following the
[Locality of Behavior](https://htmx.org/essays/locality-of-behaviour/) design principle,
you have a single file for both cases. See below for examples.## Install
It's just `pip install jinja2-fragments` and you're all set. It's a pure Python package
that only needs `jinja2` (for obvious reasons!).## Usage
This is an example of how to use the library with vanilla Jinja2. Given the template `page.html.jinja2`:
```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, do:
```python
from jinja2 import Environment, FileSystemLoader, select_autoescape
from jinja2_fragments import render_blockenvironment = Environment(
loader=FileSystemLoader("my_templates"),
autoescape=select_autoescape(("html", "jinja2"))
)
rendered_html = render_block(
environment, "page.html.jinja2", "content", magic_number=42
)
```And this will only render:
```htmlThis is the magic number: 42.
```### Rendering multiple blocks
With the variant `render_blocks` (notice the plural) it is also possible to render
multiple blocks from the same template and concatenate them all to return them in a
single response. This enables easier
[out-of-band updates](https://htmx.org/attributes/hx-swap-oob/) when using HTMX.## Usage with Flask
If you want to use Jinja2 Fragments with Flask, assuming the same template as the
example above, do:```python
from flask import Flask, render_template
from jinja2_fragments.flask import render_blockapp = 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)
```## Usage with Quart
If you want to use Jinja2 Fragments with Quart, assuming the same template as the
example above, do:```python
from quart import Quart, render_template
from jinja2_fragments.quart import render_blockapp = 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)
```
## Usage with FastAPIYou can also use Jinja2 Fragments with FastAPI. In this case, Jinja2 Fragments has a wrapper around the FastAPI `Jinja2Templates` object called `Jinja2Blocks`.
It functions exactly the same, but allows you to include an optional parameter to the `TemplateResponse` that includes the `block_name` you want to render.
Assuming the same template as the examples above:
```py
from fastapi import FastAPI
from fastapi.requests import Request
from jinja2_fragments.fastapi import Jinja2Blocksapp = FastAPI()
templates = Jinja2Blocks(directory="path/to/templates")
@app.get("/full_page")
async def full_page(request: Request):
return templates.TemplateResponse(
"page.html.jinja2",
{"request": request, "magic_number": 42}
)@app.get("/only_content")
async def only_content(request: Request):
return templates.TemplateResponse(
"page.html.jinja2",
{"request": request, "magic_number": 42},
block_name="content"
)
```## Usage with Sanic
You can use jinja2-fragments's `render()` with Sanic as a drop-in replacement of the Sanic template extension's `render()`. Your request context and environment configuration will work the same as before. You must have `sanic_ext` and `Jinja2` installed.By default, the full page is rendered (`block=None`) unless you provide a `block` keyword argument.
```py
from sanic import Sanic, Request
import sanic_ext
from jinja2_fragments.sanic import renderapp = 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}
)
```## Usage with Litestar
You can use Jinja2 Fragments with Litestar by using the `LitestarHTMXTemplate` class. This gives you access to the `block_name` parameter when rendering the template.By default, the full page is rendered unless you provide a `block_name` keyword argument.
```py
from litestar.contrib.htmx.request import HTMXRequest
from litestar import get, Litestar
from litestar.response import Templatefrom 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,
)
)
```## How to collaborate
This project uses pre-commit hooks to run black, isort, pyupgrade and flake8 on each commit. To have that running
automatically on your environment, install the project with:```shell
pip install -e .[dev]
```And then run once:
```shell
pre-commit install
```From now on, every time you commit your files on this project, they will be automatically processed by the tools listed
above.## How to run tests
You can install pytest and other required dependencies with:
```shell
pip install -e .[tests]
```And then run the test suite with:
```shell
pytest
```