Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/air/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .responses import AirResponse as AirResponse
from .responses import RedirectResponse as RedirectResponse
from .responses import TagResponse as TagResponse
from .responses import StringResponse as StringResponse
from .tags import Children as Children
from .tags import (
H1 as H1,
Expand Down
15 changes: 15 additions & 0 deletions src/air/encoders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import air
from starlette.templating import _TemplateResponse
from fastapi import encoders
from fastapi.templating import Jinja2Templates
from typing import Dict, Type, Callable, Any

def render_template_response_to_string(request: air.Request, template_name: str, context: dict, templates: Jinja2Templates) -> str:
template = templates.get_template(template_name)
content = template.render({"request": request, **context})
return content

ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
_TemplateResponse: render_template_response_to_string
}

10 changes: 10 additions & 0 deletions src/air/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,13 @@ def render(self, content: Any) -> bytes:
if isinstance(content, dict):
content = dict_to_ft_component(content)
return content.render().encode("utf-8")


class StringResponse(Response):
"""Response class to handle air.tags.Tags or HTML (from Jinja2)."""

media_type = "text/html; charset=utf-8"

def render(self, content: str) -> bytes:
"""Render Tag elements to bytes of HTML."""
return content.encode("utf-8")
42 changes: 27 additions & 15 deletions src/air/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from fastapi.templating import Jinja2Templates

from .responses import StringResponse
from .requests import Request
from .tags import Tag

Expand Down Expand Up @@ -36,6 +37,7 @@ async def home(request: Request):
def __init__(self, directory: str):
"""Initialize with template directory path"""
self.templates = Jinja2Templates(directory=directory)
self.directory = directory

def __call__(
self,
Expand All @@ -44,18 +46,28 @@ def __call__(
context: dict[Any, Any] | None = None,
**kwargs,
):
"""Render template with request and context. If an Air Tag
is found in the context, try to render it.
"""
if context is None:
context = {}
if kwargs:
context = context | kwargs

# Attempt to render any Tags in the contect
for k, v in context.items():
if isinstance(v, Tag) and hasattr(v, "render"):
context[k] = v.render()
return self.templates.TemplateResponse(
request=request, name=name, context=context
)
return StringResponse('zsdfdfds')

# def __call__(
# self,
# request: Request,
# name: str,
# context: dict[Any, Any] | None = None,
# **kwargs,
# ):
# """Render template with request and context. If an Air Tag
# is found in the context, try to render it.
# """
# if context is None:
# context = {}
# if kwargs:
# context = context | kwargs

# # Attempt to render any Tags in the contect
# for k, v in context.items():
# if isinstance(v, Tag) and hasattr(v, "render"):
# context[k] = v.render()

# return self.templates.TemplateResponse(
# request=request, name=name, context=context
# )
1 change: 1 addition & 0 deletions tests/templates/simple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Very simple Jinja tag {{value}}</p>
16 changes: 16 additions & 0 deletions tests/test_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,19 @@ def index(request: Request):
response.text
== """<html>\n <head>\n <title>Jinja+Air Tags</title>\n </head>\n <body>\n <h1>Jinja+Air Tags</h1>\n <main><p>Air Tags work great with Jinja</p></main>\n </body>\n</html>"""
)


def test_jinja_within_air():
app = Air()
jinja = JinjaRenderer(directory="tests/templates")

@app.page
def index(request: air.Request):
return air.Div(
jinja(request, 'simple.html', value=42)
)

client = TestClient(app)
response = client.get("/")
assert response.status_code == 200
assert response.text == '<div><p>Very simple Jinja tag 42</p></div>'
Loading