Templates¶
Lilya is not inherently tied to any specific templating engine, but Jinja2 stands out as an excellent choice due to its proven origins and widely adoption in the Python world.
Jinja2Template¶
This is what Lilya brings out of the box and allows serving HTML via the handlers.
from lilya.templating import Jinja2Template
Parameters¶
directory
: A string, os.Pathlike, or a list of strings or os.Pathlike indicating a directory path.env
: Any differentjinja2.Environment
instance (Optional).**options
: Additional keyword arguments to pass to the Jinja2 environment.
Use of Jinja2Template¶
Lilya brings a pre-configured Jinja2Template
configuration that it will be probably what you will
want to use. In case you want a different jinja2.Enviroment
, that can be also passed when instantiating
the Jinja2Template
.
from lilya.apps import Lilya
from lilya.requests import Request
from lilya.routing import Include, Path
from lilya.staticfiles import StaticFiles
from lilya.templating import Jinja2Template
templates = Jinja2Template(directory="templates")
async def homepage(request: Request):
return templates.get_template_response(request, "index.html")
app = Lilya(
debug=True,
routes=[
Path("/", homepage),
Include("/static", StaticFiles(directory="static"), name="static"),
],
)
Templates response parameters¶
The get_template_response function expects the following arguments:
request
(required): The HTTP request object.name
(required): The name of the template to render.context
(optional): A dictionary allowing you to include dynamic data in the template rendering process.
Any additional arguments or keyword arguments provided will be passed directly to TemplateResponse
.
Optional Arguments¶
status_code
(int, optional): The status code of the response. Defaults to 200.background
(BackgroundTask, optional): An instance of BackgroundTask. Defaults to None.headers
(dict[str, Any], optional): A dictionary of response headers. Defaults to None.media_type
(str, optional): The media type of the response. Defaults to "text/html".
You can pass these arguments either as keyword arguments or positional arguments, depending on your preference.
Warning
It's imperative to include the incoming request instance as part of the template context.
The Jinja2 template context automatically incorporates a url_for
function, allowing correct hyperlinking to other pages within the application.
For instance, static files can be linked from within HTML templates:
<link href="{{ url_for('static', path='/css/app.min.css') }}" rel="stylesheet" />
Should you wish to utilize custom filters, you will need to update the env
property of Jinja2Template
:
from lilya.templating import Jinja2Template
def marked_filter(text): ...
templates = Jinja2Template(directory="templates")
templates.env.filters["marked"] = marked_filter
The jinja2.Environment
¶
Lilya accepts a preconfigured jinja2.Environment instance by
passing it inside the env
attribute when instantiaing the Jinja2Template
.
import jinja2
from lilya.templating import Jinja2Template
env = jinja2.Environment(...)
templates = Jinja2Template(env=env)
Context Processors¶
A context processor is a function that returns a dictionary to be merged into a template context. Each function takes only one argument,
request
, and must return a dictionary to be added to the context.
A typical use case for template processors is to enhance the template context with shared variables.
from lilya.requests import Request
def application_context(request: Request):
return {"app": request.app}
Registering Context Processors¶
To register context processors, pass them to the context_processors
argument of the Jinja2Template
class.
from lilya.requests import Request
from lilya.templating import Jinja2Template
def settings_context(request: Request):
return {"settings": request.app.settings}
templates = Jinja2Template(
directory="templates",
context_processors=[settings_context],
)
Custom Jinja2 Environment¶
Jinja2Template
accepts all options supported by the Jinja2 Environment
.
This grants greater control over the Environment
instance created by Lilya.
For the list of options available to Environment
, refer to the Jinja2 documentation
here.
from lilya.templating import Jinja2Template
templates = Jinja2Template(
directory="templates",
autoescape=False,
auto_reload=True,
)
Asynchronous Template Rendering¶
While Jinja2 supports asynchronous template rendering, it is advisable to avoid including logic in templates that trigger database lookups or other I/O operations.
A recommended practice is to ensure that your endpoints handle all I/O operations. For instance, perform database queries within the view and include the final results in the context. This approach helps keep templates focused on presentation logic rather than I/O operations.