ZeroIntensity / view.py

The Batteries-Detachable Web Framework
https://view.zintensity.dev
MIT License
206 stars 15 forks source link

Template Rendering #92

Closed ZeroIntensity closed 6 months ago

ZeroIntensity commented 7 months ago

Feature description

With the introduction of the new component API (#12), a template rendering system should also be implemented to support features from other libraries. This will be pretty easy to implement.

Feature example API

from view import new_app, template

app = new_app()

@app.get("/")
async def index():
    return await template("hello")  # this is I/O (file reading), so it should be async

Anything else?

Generally, Python templating uses Jinja, so naturally that would be the first option. However, other template engines could be introduced and selected via parameters to template or the configuration. The configuration will also specify a templates directory.

The signature of template will probably end up looking like:

async def template(
    name: str | Path,
    **parameters: Any,
    directory: str | Path,
    engine: Literal["jinja"] = "jinja",  # add more engines here later
) -> HTML: ...
ZeroIntensity commented 6 months ago

There does need to be a configuration setting for defining template locations. This will likely be something like:

[app]
templates = "./templates"

This does give me an idea for mixing different loader directories with different template paths, but that's for another issue.

ZeroIntensity commented 6 months ago

In terms of engines, View will implement it's own template engine. This will also remove the "beginner" tag from this issue. It doesn't have to be anything too fancy, just something like:

<view template="index.html" /> <! -- includes a separate template -->
<view page="/" /> <! -- includes a separate page -->
<view ref="hello_world" /> <! -- takes the hello_world variable from the scope -->

<view iter="hello_world" item="i">
    <view ref="i.foo" />
</view>

<view condition>
    <view if="hello_world == 'test'">
        <p>hello world is test</p>
    </view>
    <view else if="hello_world == 'not a test'">
        <p>hello world is not a test</p>
     <view>
     <view else>
        <p>idk what hello world is</p>
    </view>
</view>

And of course, for batteries-detachable, I would like to support the following engines: