maces / fastapi-htmx

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

Problem when using with a pydantic model #42

Open hf-sheese opened 4 months ago

hf-sheese commented 4 months ago

I want to write a simple healthcheck endpoint with pydantic and call it using htmx. The endpoint returns a pydantic model. However, if I want to run the endpoint, I get: "AttributeError: 'dict' object has no attribute 'encode'. I have to manually convert the model to a dictionary using model_dump to solve this problem. Here is the sourcecode: FastAPI endpoint:

@router.get("/health", response_model=HealthcheckResult)
async def health_check():

    result = HealthcheckResult(passed_all_checks=True)
    return result

htmx wrapper:

@router.get("/health", response_class=HTMLResponse)
@htmx("health", "index", health_check)
async def health_check_htmx(
    request: Request,
):
    pass

pydantic model:

`class` HealthcheckResult(BaseModel):

    passed_all_checks: bool
maces commented 3 months ago

Up until now only dicts are supported as you noticed. Will label this as a possible enhancement. Expectation wise we are talking about transparent handling of my_model.model_dump(), right?

hf-kklein commented 3 months ago

Our expectation is: If my endpoint returns a Pydantic model, then the model.model_dump(mode="json") should be called automatically and the dumped dict should be passed on to the jinja2 template.

My best guess is, that it could be handled around here:

https://github.com/maces/fastapi-htmx/blob/a4f0b8ab82473a6110ab8d7e609a2e6b1a208b0d/fastapi_htmx/htmx.py#L145

Instead of only checking for instance of mapping there should also be a check like:

if isinstance(response, BaseModel):
   response = response.model_dump(mode="json")
if not isinstance(response, Mapping):
    ...

A type-checker will complain about this, but I guess it would work.