pydantic / FastUI

Build better UIs faster.
https://fastui-demo.onrender.com
MIT License
8.23k stars 317 forks source link

Select Forms validation and json model generation #349

Open uniqpr0 opened 2 months ago

uniqpr0 commented 2 months ago

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?

orfisko commented 1 month ago

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!

uniqpr0 commented 1 month ago

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'))]