FastUI
FastUI copied to clipboard
Select Forms validation and json model generation
I'm trying to use that part of code from example
@app.get('/api/search', response_model=SelectSearchResponse)
async def search_view(request: Request, q: str) -> SelectSearchResponse:
path_ends = f'name/{q}' if q else 'all'
client: AsyncClient = request.app.state.httpx_client
r = await client.get(f'https://restcountries.com/v3.1/{path_ends}')
if r.status_code == 404:
options = []
else:
r.raise_for_status()
data = r.json()
if path_ends == 'all':
# if we got all, filter to the 20 most populous countries
data.sort(key=lambda x: x['population'], reverse=True)
data = data[0:20]
data.sort(key=lambda x: x['name']['common'])
regions = defaultdict(list)
for co in data:
regions[co['region']].append({'value': co['cca3'], 'label': co['name']['common']})
options = [{'label': k, 'options': v} for k, v in regions.items()]
return SelectSearchResponse(options=options)
class SelectForm(BaseModel):
search_select_single: str = Field(json_schema_extra={'search_url': '/search'})
@app.post('/api/city/add', response_model=FastUI, response_model_exclude_none=True)
async def select_form_post(form: Annotated[SelectForm, fastui_form(SelectForm)]):
print(form)
return [c.FireEvent(event=GoToEvent(url='/'))]
But error
/pydantic/json_schema.py", line 338, in build_schema_type_to_method
raise TypeError(
TypeError: No method for generating JsonSchema for core_schema.type='complex' (expected: GenerateJsonSchema.complex_schema)
pydantic 2.8.2 pydantic-core 2.23.1
What is the problem?
I think this is a more general Pydantic issue. I am having the same problem in my fastapi application. Correction: solved in 2.9.0!
I think this is a more general Pydantic issue. I am having the same problem in my fastapi application. Correction: solved in 2.9.0!
Actually i solved it like that in example with mongodb version Pydantic 2.6.1 and Fastui 0.6.0
from fastui.forms import fastui_form, SelectSearchResponse
class CityAdd(BaseModel):
city: str = Field(json_schema_extra={'search_url': '/city/search'}, title='City')
@app.get('/city/search', response_model=SelectSearchResponse)
async def search_view(request: Request, q: str | None = None) -> SelectSearchResponse:
if q is None:
cities = citiesListEntity(await (request.app.database.city.find()).to_list(None))
else:
cities = citiesListEntity(await (request.app.database.city.find({"name": {"$regex": q}})).to_list(None))
@app.get("/api/city/add", response_model=FastUI, response_model_exclude_none=True)
async def add_city_page(request: Request):
return [
c.Page(
components=[
c.Link(components=[c.Button(text='Return')], on_click=BackEvent()),
c.Heading(text='Add city', level=2),
c.ModelForm(
model=CityAdd,
submit_url="/api/city/create",
)
]
)
]
@app.post('/api/city/create', response_model=FastUI, response_model_exclude_none=True)
async def city_create(request: Request,
payload: Annotated[CityAdd, fastui_form(CityAdd)],):
print(payload.model_dump())
return [c.FireEvent(event=GoToEvent(url='/cities'))]