Skip to content

Commit

Permalink
feat: location + basemodel encode
Browse files Browse the repository at this point in the history
  • Loading branch information
hxjo committed Apr 21, 2024
1 parent 47cbea0 commit 7b3907f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
16 changes: 14 additions & 2 deletions backend/inertia/inertia.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import logging

from fastapi import Request
from fastapi import Request, Response, status
from fastapi.responses import JSONResponse, HTMLResponse
from typing import Any, Callable, Dict, Optional, TypeVar, TypedDict, Union, cast
import json
import requests
from pydantic import BaseModel

from .config import InertiaConfig
from .exceptions import InertiaVersionConflictException
Expand Down Expand Up @@ -104,7 +105,11 @@ def _deep_transform_callables(
cls, prop: Union[Callable[..., Any], Dict[str, Any]]
) -> Any:
if not isinstance(prop, dict):
return prop() if callable(prop) else prop
if callable(prop):
return prop()
if isinstance(prop, BaseModel):
return prop.model_dump()
return prop

prop_ = prop.copy()
for key in list(prop_.keys()):
Expand Down Expand Up @@ -178,6 +183,13 @@ def flash(self, message: str, category: str = "primary") -> None:
message_: FlashMessage = {"message": message, "category": category}
self._request.session["_messages"].append(message_)

@staticmethod
def location(url: str) -> Response:
return Response(
status_code=status.HTTP_409_CONFLICT,
headers={"X-Inertia-Location": url},
)

async def render(
self, component: str, props: Optional[Dict[str, Any]] = None
) -> HTMLResponse | JSONResponse:
Expand Down
7 changes: 6 additions & 1 deletion backend/inertia/tests/test_pydantic_basemodel_are_encoded.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

InertiaDep = Annotated[Inertia, Depends(inertia_dependency_factory(InertiaConfig()))]


class Person(BaseModel):
name: str
age: int


PROPS = {
"person": {
"name": "John Doe",
Expand All @@ -35,7 +37,9 @@ class Person(BaseModel):
async def index(inertia: InertiaDep) -> InertiaResponse:
name = PROPS["person"]["name"]
age = PROPS["person"]["age"]
return await inertia.render(COMPONENT, {"person": Person(name=cast(str, name), age=cast(int, age))})
return await inertia.render(
COMPONENT, {"person": Person(name=cast(str, name), age=cast(int, age))}
)


def test_pydantic_basemodel_are_encoded_on_json_response() -> None:
Expand All @@ -50,6 +54,7 @@ def test_pydantic_basemodel_are_encoded_on_json_response() -> None:
"version": "1.0",
}


def test_pydantic_basemodel_are_encoded_on_html_response() -> None:
with TestClient(app) as client:
response = client.get("/")
Expand Down
8 changes: 0 additions & 8 deletions backend/inertia/utils.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
from json import JSONEncoder

from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
from typing import Callable, Any


def model_to_dict(model: BaseModel) -> dict[str, Any]:
return model.model_dump(exclude={"password"})


class InertiaJsonEncoder(JSONEncoder):
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)

def encode(self, value: Any) -> Any:
if isinstance(value, BaseModel):
return model_to_dict(value)

return jsonable_encoder(value)


Expand Down

0 comments on commit 7b3907f

Please sign in to comment.