fix(views): make Restaurant JSON-safe before passing to Jinja
All four CMS pages (menu / orders / kds / settings) crashed with
TypeError: JSONEncoder.default() missing 1 required positional
argument: 'o'
because templates do `{{ restaurant | tojson | safe }}`. `tojson`
runs Python's stdlib `json.JSONEncoder` which can't serialize the
`datetime` on `Restaurant.time` (or any other datetime nested in
the model). The browser saw '500 / 'o'' (KeyError-flavored).
Pydantic v1's .json() handles datetime correctly (ISO 8601). New
helper _restaurant_jsonable rounds-trips the Restaurant via .json()
+ json.loads() and returns a fully JSON-safe dict, then all four
view handlers pass that instead of restaurant.dict().
This commit is contained in:
parent
d4b1f4be53
commit
e98f82dced
1 changed files with 21 additions and 4 deletions
25
views.py
25
views.py
|
|
@ -15,6 +15,7 @@ Pages
|
|||
All pages require a logged-in LNbits user (check_user_exists).
|
||||
"""
|
||||
|
||||
import json
|
||||
from http import HTTPStatus
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
|
|
@ -26,6 +27,7 @@ from lnbits.decorators import check_user_exists
|
|||
from lnbits.helpers import template_renderer
|
||||
|
||||
from .crud import get_restaurant_by_slug
|
||||
from .models import Restaurant
|
||||
|
||||
restaurant_generic_router = APIRouter()
|
||||
|
||||
|
|
@ -34,6 +36,21 @@ def restaurant_renderer():
|
|||
return template_renderer(["restaurant/templates"])
|
||||
|
||||
|
||||
def _restaurant_jsonable(restaurant: Restaurant) -> dict:
|
||||
"""
|
||||
Convert a Restaurant pydantic model to a plain JSON-serializable
|
||||
dict for Jinja's `tojson` filter.
|
||||
|
||||
`restaurant.dict()` returns a dict with a `datetime` on `time`,
|
||||
which Python's stdlib `JSONEncoder` (used by Jinja `tojson`) can't
|
||||
serialize — it errors out as
|
||||
TypeError: JSONEncoder.default() missing 1 required positional argument: 'o'
|
||||
Pydantic v1's `.json()` knows how to serialize datetime as
|
||||
ISO-8601, so we round-trip via JSON to get a clean dict.
|
||||
"""
|
||||
return json.loads(restaurant.json())
|
||||
|
||||
|
||||
@restaurant_generic_router.get("/", response_class=HTMLResponse)
|
||||
async def index(request: Request, user: User = Depends(check_user_exists)):
|
||||
return restaurant_renderer().TemplateResponse(
|
||||
|
|
@ -56,7 +73,7 @@ async def menu_builder(
|
|||
{
|
||||
"request": request,
|
||||
"user": user.json(),
|
||||
"restaurant": restaurant.dict(),
|
||||
"restaurant": _restaurant_jsonable(restaurant),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -75,7 +92,7 @@ async def orders(
|
|||
{
|
||||
"request": request,
|
||||
"user": user.json(),
|
||||
"restaurant": restaurant.dict(),
|
||||
"restaurant": _restaurant_jsonable(restaurant),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -94,7 +111,7 @@ async def kds(
|
|||
{
|
||||
"request": request,
|
||||
"user": user.json(),
|
||||
"restaurant": restaurant.dict(),
|
||||
"restaurant": _restaurant_jsonable(restaurant),
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -113,6 +130,6 @@ async def settings_page(
|
|||
{
|
||||
"request": request,
|
||||
"user": user.json(),
|
||||
"restaurant": restaurant.dict(),
|
||||
"restaurant": _restaurant_jsonable(restaurant),
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue