Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add minjinja #2250

Merged
merged 25 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7998b2f
feat: add minjinja
euri10 Aug 26, 2023
00e91d5
feat: add minjinja, more tests
euri10 Aug 28, 2023
bbd3960
feat: add minjinja, added url_for tests
euri10 Aug 28, 2023
8dfae6a
feat: add minjinja, added context tests, seems we have something to d…
euri10 Aug 28, 2023
60d9098
feat: add minjinja, added working csrf token tests
euri10 Aug 28, 2023
1c16948
fix: not a fix but demonstrates that using | safe filter on url_for w…
euri10 Aug 28, 2023
170cd6c
fix: revert and dont use safe in tests
euri10 Aug 28, 2023
34b9f62
fix: merge main
euri10 Aug 31, 2023
de49e91
Merge remote-tracking branch 'origin/euri10/minjinja' into euri10/min…
euri10 Sep 1, 2023
0363f40
fix: change tests to mimic what minijinja would expect
euri10 Sep 1, 2023
1696261
fix: remove undeeded Environment config
euri10 Sep 2, 2023
20e6305
Merge branch 'main' into euri10/minjinja
euri10 Sep 4, 2023
0219d7c
fix: pin anyio because private imports broke CI
euri10 Sep 6, 2023
a951de7
Merge branch 'main' into euri10/minjinja
euri10 Sep 6, 2023
76f2f05
Merge branch 'main' into euri10/minjinja
Goldziher Sep 7, 2023
ae44120
fix: add docs for minijinja
euri10 Sep 8, 2023
75b3065
fix: tests for running templates
euri10 Sep 8, 2023
49072a4
fix: poetry lock
euri10 Sep 8, 2023
079e673
fix: anyio unpin
euri10 Sep 8, 2023
90e15b0
fix: some tests didnt use proper docs examples
euri10 Sep 8, 2023
4c80a59
fix: added more tabs for minijinja
euri10 Sep 8, 2023
56c0d50
Merge branch 'main' into euri10/minjinja
euri10 Sep 8, 2023
b323682
fix: removed useless debug in mako examples
euri10 Sep 8, 2023
be356a4
fix: auto rewite of the mako template by linters, tests will fail
euri10 Sep 8, 2023
970f794
fix: mako tests contains a \n at the end of the generated string
euri10 Sep 8, 2023
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 .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ repos:
jsbeautifier,
mako,
mongomock_motor,
minijinja,
msgspec,
multidict,
opentelemetry-instrumentation-asgi,
Expand Down
3 changes: 1 addition & 2 deletions docs/examples/templating/engine_instance_jinja.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.template.config import TemplateConfig

template_config = TemplateConfig(engine=JinjaTemplateEngine)
template_config.engine_instance.engine.globals["foo"] = "bar"
template_config = TemplateConfig(engine=JinjaTemplateEngine, directory="templates")
3 changes: 1 addition & 2 deletions docs/examples/templating/engine_instance_mako.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from litestar.contrib.mako import MakoTemplateEngine
from litestar.template.config import TemplateConfig

template_config = TemplateConfig(engine=MakoTemplateEngine)
template_config.engine_instance.engine.has_template("foo")
template_config = TemplateConfig(engine=MakoTemplateEngine, directory="templates")
4 changes: 4 additions & 0 deletions docs/examples/templating/engine_instance_minijinja.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from litestar.contrib.minijnja import MiniJinjaTemplateEngine
from litestar.template.config import TemplateConfig

template_config = TemplateConfig(engine=MiniJinjaTemplateEngine, directory="templates")
2 changes: 1 addition & 1 deletion docs/examples/templating/returning_templates_jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def index(name: str) -> Template:
app = Litestar(
route_handlers=[index],
template_config=TemplateConfig(
directory=Path("templates"),
directory=Path(__file__).parent / "templates",
engine=JinjaTemplateEngine,
),
)
2 changes: 1 addition & 1 deletion docs/examples/templating/returning_templates_mako.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def index(name: str) -> Template:
app = Litestar(
route_handlers=[index],
template_config=TemplateConfig(
directory=Path("templates"),
directory=Path(__file__).parent / "templates",
engine=MakoTemplateEngine,
),
)
20 changes: 20 additions & 0 deletions docs/examples/templating/returning_templates_minijinja.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pathlib import Path

from litestar import Litestar, get
from litestar.contrib.minijnja import MiniJinjaTemplateEngine
from litestar.response import Template
from litestar.template.config import TemplateConfig


@get(path="/")
def index(name: str) -> Template:
return Template(template_name="hello.html.minijinja", context={"name": name})


app = Litestar(
route_handlers=[index],
template_config=TemplateConfig(
directory=Path(__file__).parent / "templates",
engine=MiniJinjaTemplateEngine,
),
)
13 changes: 13 additions & 0 deletions docs/examples/templating/template_engine_minijinja.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pathlib import Path

from litestar import Litestar
from litestar.contrib.minijnja import MiniJinjaTemplateEngine
from litestar.template.config import TemplateConfig

app = Litestar(
route_handlers=[],
template_config=TemplateConfig(
directory=Path("templates"),
engine=MiniJinjaTemplateEngine,
),
)
2 changes: 1 addition & 1 deletion docs/examples/templating/template_functions_jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def register_template_callables(engine: JinjaTemplateEngine) -> None:


template_config = TemplateConfig(
directory=Path("templates"),
directory=Path(__file__).parent / "templates",
engine=JinjaTemplateEngine,
engine_callback=register_template_callables,
)
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/templating/template_functions_mako.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def register_template_callables(engine: MakoTemplateEngine) -> None:


template_config = TemplateConfig(
directory=Path("templates"),
directory=Path(__file__).parent / "templates",
engine=MakoTemplateEngine,
engine_callback=register_template_callables,
)
Expand Down
34 changes: 34 additions & 0 deletions docs/examples/templating/template_functions_minijinja.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import functools
from pathlib import Path
from typing import Any, Dict

from litestar import Litestar, get
from litestar.contrib.minijnja import MiniJinjaTemplateEngine, minijinja_from_state
from litestar.response import Template
from litestar.template.config import TemplateConfig


def my_template_function(ctx: Dict[str, Any]) -> str:
return ctx.get("my_context_key", "nope")


def register_template_callables(engine: MiniJinjaTemplateEngine) -> None:
engine.register_template_callable(
key="check_context_key",
template_callable=functools.partial(minijinja_from_state, my_template_function),
)


template_config = TemplateConfig(
directory=Path(__file__).parent / "templates",
engine=MiniJinjaTemplateEngine,
engine_callback=register_template_callables,
)


@get("/")
def index() -> Template:
return Template(template_name="index.html.minijinja")


app = Litestar(route_handlers=[index], template_config=template_config)
1 change: 1 addition & 0 deletions docs/examples/templating/templates/hello.html.minijinja
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello <strong>{{ name }}</strong>
1 change: 1 addition & 0 deletions docs/examples/templating/templates/index.html.minijinja
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<strong>check_context_key: </strong>{{ check_context_key() }}
2 changes: 1 addition & 1 deletion docs/migration/flask.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ Templates
Flask comes with the `Jinja <https://jinja.palletsprojects.com/en/3.1.x/>`_ templating
engine built-in. You can use Jinja with Litestar as well, but you’ll need to install it
explicitly. You can do by installing Litestar with ``pip install litestar[jinja]``.
In addition to Jinja, Litestar supports `Mako <https://www.makotemplates.org/>`_ templates as well.
In addition to Jinja, Litestar supports `Mako <https://www.makotemplates.org/>`_ and `Minijinja <https:/mitsuhiko/minijinja/tree/main/minijinja-py>`_ templates as well.

.. tab-set::
.. tab-item:: Flask
Expand Down
73 changes: 66 additions & 7 deletions docs/usage/templating.rst
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
Templating
==========

Litestar has built-in support for both the `Jinja2 <https://jinja.palletsprojects.com/en/3.0.x/>`_
and `Mako <https://www.makotemplates.org/>`_ template engines, as well as abstractions to
Litestar has built-in support for `Jinja2 <https://jinja.palletsprojects.com/en/3.0.x/>`_
, `Mako <https://www.makotemplates.org/>`_ and `Minijinja <https:/mitsuhiko/minijinja/tree/main/minijinja-py>`_ template engines, as well as abstractions to
make use of any template engine you wish.

Template engines
----------------

To stay lightweight, a Litestar installation does not include the *Jinja* or *Mako*
To stay lightweight, a Litestar installation does not include the *Jinja*, *Mako* or *Minijinja*
libraries themselves. Before you can start using them, you have to install it via the
respective extra:


* ``pip install litestar[jinja]`` for Jinja2
* ``pip install litestar[mako]`` for Mako
* ``pip install litestar[minijinja]`` for Minijinja

.. tip::

Expand All @@ -41,6 +42,12 @@ To register one of the built-in template engines you simply need to pass it to t
.. literalinclude:: /examples/templating/template_engine_mako.py
:language: python

.. tab-item:: MiniJinja
:sync: minijinja

.. literalinclude:: /examples/templating/template_engine_minijinja.py
:language: python

.. note::

The ``directory`` parameter passed to :class:`TemplateConfig <litestar.template.TemplateConfig>`
Expand Down Expand Up @@ -112,12 +119,18 @@ If you need to access the template engine instance, you can do so via the
.. literalinclude:: /examples/templating/engine_instance_jinja.py
:language: python

.. tab-item:: mako
.. tab-item:: Mako
:sync: mako

.. literalinclude:: /examples/templating/engine_instance_mako.py
:language: python

.. tab-item:: MiniJinja
:sync: minijinja

.. literalinclude:: /examples/templating/engine_instance_minijinja.py
:language: python

Template responses
------------------

Expand All @@ -132,12 +145,17 @@ your route handlers:
.. literalinclude:: /examples/templating/returning_templates_jinja.py
:language: python

.. tab-item:: mako
.. tab-item:: Mako
:sync: mako

.. literalinclude:: /examples/templating/returning_templates_mako.py
:language: python

.. tab-item:: MiniJinja
:sync: minijinja

.. literalinclude:: /examples/templating/returning_templates_minijinja.py
:language: python

* ``name`` is the name of the template file within on of the specified directories. If
no file with that name is found, a :class:`TemplateNotFoundException <.exceptions.TemplateNotFoundException>`
Expand Down Expand Up @@ -176,7 +194,7 @@ Accessing ``app.state.key`` for example would look like this:
</html>


.. tab-item:: mako
.. tab-item:: Mako
:sync: mako

.. code-block:: html
Expand All @@ -191,6 +209,19 @@ Accessing ``app.state.key`` for example would look like this:
</html>


.. tab-item:: MiniJinja
:sync: minijinja

.. code-block:: html

<html>
<body>
<div>
<span>My state value: {{request.app.state.some_key}}</span>
</div>
</body>
</html>


Adding CSRF inputs
^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -221,7 +252,7 @@ With that in place, you can now insert the CSRF input field inside an HTML form:
</body>
</html>

.. tab-item:: mako
.. tab-item:: Mako
:sync: mako

.. code-block:: html
Expand All @@ -240,6 +271,24 @@ With that in place, you can now insert the CSRF input field inside an HTML form:
</body>
</html>

.. tab-item:: MiniJinja
:sync: minijinja

.. code-block:: html

<html>
<body>
<div>
<form action="https://myserverurl.com/some-endpoint" method="post">
{{ csrf_input }}
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname">
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
</div>
</body>
</html>


The input holds a CSRF token as its value and is hidden so users cannot see or interact with it. The token is sent
Expand Down Expand Up @@ -319,6 +368,16 @@ the call method. For example:
:language: html
:caption: templates/index.html.mako

.. tab-item:: Minijinja
:sync: minijinja

.. literalinclude:: /examples/templating/template_functions_minijinja.py
:caption: template_functions.py
:language: python

.. literalinclude:: /examples/templating/templates/index.html.minijinja
:language: html
:caption: templates/index.html.minijinja

Run the example with ``uvicorn template_functions:app`` , visit http://127.0.0.1:8000, and
you'll see
Expand Down
Loading