maces / fastapi-htmx

Extension for FastAPI to make HTMX easier to use.
GNU Lesser General Public License v3.0
229 stars 9 forks source link

htmx_init template path not usable for multiple template dirs #11

Closed krawalli closed 7 months ago

krawalli commented 8 months ago

i have a more complex app and separated templates directories. htmx_init can be used only once, cause its setting is global. How to use for multiple template-dirs?

Workaround: always add path to all @htmx

Wish: let the default extension be setable in htmx_init, for more DRY.

maces commented 8 months ago

Hi there, thanks for using fastapi-htmx :)

I assume your separate template directories are used for different parts of your app? Maybe split by router? I'm asking because i want to understand how this could be implemented best. Especially since the extensions internally uses a global variable 😇 for the template path. So even sub-apps do not help here at the moment.

Do you want to set all template directories with htmx_init and then select the correct template directory by slug/key on each route (like @htmx(..., template_collection=CUSTOMER_PORTAL))?

krawalli commented 8 months ago

Yes, structured and multiple router that routes are mounted in main app. Almost same problem with "url_for", since the sub routes are not mixed in one pool. They solved it by prefix the name e.g. "admin:index", "site:index" or "site:img"-

maces commented 8 months ago

So something along these lines would help here with the templates, right?

from pathlib import Path

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

from fastapi_htmx import htmx, htmx_init

SITE_COLLECTION = "site"
ADMIN_COLLECTION = "admin"

app = FastAPI()
htmx_init(
    templates={
        SITE_COLLECTION: Jinja2Templates(directory=Path("my_app") / SITE_COLLECTION / "templates"),
        ADMIN_COLLECTION: Jinja2Templates(directory=Path("my_app") / ADMIN_COLLECTION / "templates"),
    }
)

def construct_customers():
    return {"customers": ["John Doe", "Jane Doe"]}

def construct_root_page():
    return {"greeting": "Hello World", **construct_customers()}

@app.get("/", response_class=HTMLResponse)
@htmx(
    {"template_name": "index", "collection_name": SITE_COLLECTION},
    {"template_name": "index", "collection_name": SITE_COLLECTION},
)
async def root_page(request: Request):
    return construct_root_page()

@app.get("/admin", response_class=HTMLResponse)
@htmx(
    {"template_name": "admin", "collection_name": ADMIN_COLLECTION},
    {"template_name": "index", "collection_name": SITE_COLLECTION},
    full_template_constructor=construct_root_page,
)
async def admin_page(request: Request):
    return {"greeting": "Hello Admin"}

@app.get("/customers", response_class=HTMLResponse)
@htmx(
    {"template_name": "customers", "collection_name": SITE_COLLECTION},
    {"template_name": "index", "collection_name": SITE_COLLECTION},
    partial_template_constructor=construct_customers,
    full_template_constructor=construct_root_page,
)
async def get_customers(request: Request):
    pass
krawalli commented 8 months ago

Seems better to me. Still a lot auf (d)RY stuff. E.g. my templates are not .jinja2, they are .html - It has to be declared at every @htmx

maces commented 7 months ago

@krawalli Multiple directories are now possible along with a global override for the template file extension. To test the new changes use the latest pre release pip install fastapi-htmx==0.4.0rc0. In case this works for you I'll do a proper release.

maces commented 7 months ago

Because of #18 this got released now already. Feel free to leave feedback anyway :slightly_smiling_face: