FastUI
FastUI copied to clipboard
Bug with multi select fields
There is a bug with multi select fields when only one item is selected leading to an incorrect 422 error.
E.g., when selecting only one item for the "Select Multiple" select element on https://fastui-demo.onrender.com/forms/select, the POST request throws an unexpected 422 error:
{
"detail": {
"form": [
{
"type": "list_type",
"loc": [
"select_multiple"
],
"msg": "Input should be a valid list"
}
]
}
}
This might be related to https://github.com/tiangolo/fastapi/discussions/8741. A work-around, not elegant though, would be to add the following validation to SelectForm (https://github.com/pydantic/FastUI/blob/main/demo/forms.py):
@field_validator('select_multiple', mode='before')
@classmethod
def correct_list_fields(cls, value: List[str] | str) -> List[str]:
if isinstance(value, list):
return value
else:
return [value]
Any thoughts on a neater solution?
Ye I've seen that too.
Either we'll need a way to work out which fields expect lists, or you can just add a before validator to that field to convert v to [v].
can we do something like this? may I create a separate pull request?
https://github.com/parthjoshi90/FastUI/commit/0a1b4642d650531d2954fcf7a0a2526efdecf0dd
Thanks, this looks neater to me as it does not require to add the before validation to every pydantic model separately.
We could add something like the following to check whether a field is of type array
@cache
def get_array_fields(model: pydantic.BaseModel) -> dict[str, bool]:
"""Iterate through json schema and identify which fields accept an array-like type."""
from . import json_schema
schema = _t.cast(json_schema.JsonSchemaObject, model.model_json_schema())
defs = schema.get('$defs', {})
is_array_dict = {}
for f, prop in schema['properties'].items():
field_schema, _ = json_schema.deference_json_schema(prop, defs, required=False)
# Get nested items (this only goes one level deep and does no recursion), can be improved
if 'properties' in field_schema.keys():
field_schema, _ = json_schema.deference_json_schema(field_schema['properties'], defs, required=False)
f = list(field_schema.keys())[0]
try:
is_array_dict[f] = True if json_schema.schema_is_array(field_schema) else False
except Exception:
is_array_dict[f] = False
return is_array_dict
and then use this function in the unflatten method in forms.py to replace https://github.com/pydantic/FastUI/blob/4605e6d0158926ae06642ecde2d31e66ef908c1b/src/python-fastui/fastui/forms.py#L197C9-L197C29
if len(values) == 1:
with
if len(values) == 1 and not get_array_fields()[last_key]: