Package: jinja2-fragments
Jinja2 fragmentsJinja2 Fragments allows rendering individual blocks fromJinja2 templates. This library was created
to enable the pattern ofTemplate Fragmentswith Jinja2. It's a
great pattern if you are usingHTMXor 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 theinclude tag(orJinja Partials) on the wrapping
template.With Jinja2 Fragments, following theLocality of Behaviordesign principle,
you have a single file for both cases. See below for examples.InstallIt's justpip install jinja2-fragmentsand you're all set. It's a pure Python package
that only needsjinja2(for obvious reasons!).UsageThis is an example of how to use the library with vanilla Jinja2. Given the templatepage.html.jinja2:<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>This is the title</title></head><body><h1>This is a header</h1>{% block content %}<p>This is the magic number: {{ magic_number }}.</p>{% endblock %}</body></html>If you want to render only thecontentblock, do:fromjinja2importEnvironment,FileSystemLoader,select_autoescapefromjinja2_fragmentsimportrender_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:<p>This is the magic number: 42.</p>Usage with FlaskIf you want to use Jinja2 Fragments with Flask, assuming the same template as the
example above, do:fromflaskimportFlask,render_templatefromjinja2_fragments.flaskimportrender_blockapp=Flask(__name__)@app.get("/full_page")deffull_page():returnrender_template("page.html.jinja2",magic_number=42)@app.get("/only_content")defonly_content():returnrender_block("page.html.jinja2","content",magic_number=42)Usage with QuartIf you want to use Jinja2 Fragments with Quart, assuming the same template as the
example above, do:fromquartimportQuart,render_templatefromjinja2_fragments.quartimportrender_blockapp=Quart(__name__)@app.get("/full_page")asyncdeffull_page():returnawaitrender_template("page.html.jinja2",magic_number=42)@app.get("/only_content")asyncdefonly_content():returnawaitrender_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 FastAPIJinja2Templatesobject calledJinja2Blocks.It functions exactly the same, but allows you to include an optional parameter to theTemplateResponsethat includes theblock_nameyou want to render.Assuming the same template as the examples above:fromfastapiimportFastAPIfromfastapi.requestsimportRequestfromjinja2_fragments.fastapiimportJinja2Blocksapp=FastAPI()templates=Jinja2Blocks(directory="path/to/templates")@app.get("/full_page")asyncdeffull_page(request:Request):returntemplates.TemplateResponse("page.html.jinja2",{"request":request,"magic_number":42})@app.get("/only_content")asyncdefonly_content(request:Request):returntemplates.TemplateResponse("page.html.jinja2",{"request":request,"magic_number":42},block_name="content")Usage with SanicYou can use jinja2-fragments'srender()with Sanic as a drop-in replacement of the Sanic template extension'srender(). Your request context and environment configuration will work the same as before. You must havesanic_extandJinja2installed.By default, the full page is rendered (block=None) unless you provide ablockkeyword argument.fromsanicimportSanic,Requestimportsanic_extfromjinja2_fragments.sanicimportrenderapp=Sanic(__name__)app.extend(config=sanic_ext.Config(templating_path_to_templates='path/to/templates'))@app.get('/full_page')asyncdeffull_page(request:Request):returnawaitrender('page.html.jinja2',context={"magic_number":42})asyncdefonly_content(request:Request):returnawaitrender('page.html.jinja2',block='content',context={"magic_number":42})Usage with LitestarYou can use Jinja2 Fragments with Litestar by using theLitestarHTMXTemplateclass. This gives you access to theblock_nameparameter when rendering the template.By default, the full page is rendered unless you provide ablock_namekeyword argument.frompathlibimportPathfromlitestar.contrib.htmx.requestimportHTMXRequestfromlitestarimportget,Litestarfromlitestar.responseimportTemplatefromlitestar.contrib.jinjaimportJinjaTemplateEnginefromlitestar.template.configimportTemplateConfigfromjinja2_fragments.litestarimportHTMXBlockTemplate@get('/full_page')deffull_page(request:HTMXRequest):returnHTMXBlockTemplate(template='page.html.jinja2',context={"magic_number":42})defonly_content(request:HTMXRequest):returnHTMXBlockTemplate(template='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 collaborateThis 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:pipinstall-e.[dev]And then run once:pre-commitinstallFrom now on, every time you commit your files on this project, they will be automatically processed by the tools listed
above.How to run testsYou can install pytest and other required dependencies with:pipinstall-e.[tests]And then run the test suite with:pytest