Skip to content

Commit

Permalink
Respect computed_field title in Details (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
hramezani authored May 30, 2024
1 parent 61d9b0c commit eb51d74
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
8 changes: 4 additions & 4 deletions src/python-fastui/fastui/components/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ class Details(BaseModel, extra='forbid'):

@pydantic.model_validator(mode='after')
def _fill_fields(self) -> _te.Self:
fields = {**self.data.model_fields, **self.data.model_computed_fields}

if self.fields is None:
self.fields = [
DisplayLookup(field=name, title=field.title) for name, field in self.data.model_fields.items()
]
self.fields = [DisplayLookup(field=name, title=field.title) for name, field in fields.items()]
else:
# add pydantic titles to fields that don't have them
for field in (c for c in self.fields if c.title is None):
pydantic_field = self.data.model_fields.get(field.field)
pydantic_field = fields.get(field.field)
if pydantic_field and pydantic_field.title:
field.title = pydantic_field.title
return self
Expand Down
44 changes: 43 additions & 1 deletion src/python-fastui/tests/test_tables_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ def test_display_no_fields():
# insert_assert(d.model_dump(by_alias=True, exclude_none=True))
assert d.model_dump(by_alias=True, exclude_none=True) == {
'data': {'id': 1, 'name': 'john', 'representation': '1: john'},
'fields': [{'field': 'id'}, {'title': 'Name', 'field': 'name'}],
'fields': [
{'field': 'id'},
{'title': 'Name', 'field': 'name'},
{'title': 'Representation', 'field': 'representation'},
],
'type': 'Details',
}

Expand All @@ -102,3 +106,41 @@ def test_display_fields():
'fields': [{'title': 'ID', 'field': 'id'}, {'title': 'Name', 'field': 'name'}],
'type': 'Details',
}


def test_table_respect_computed_field_title():
class Foo(BaseModel):
id: int

@computed_field(title='Foo Name')
def name(self) -> str:
return f'foo{self.id}'

foos = [Foo(id=1)]
table = components.Table(data=foos)

# insert_assert(table.model_dump(by_alias=True, exclude_none=True))
assert table.model_dump(by_alias=True, exclude_none=True) == {
'data': [{'id': 1, 'name': 'foo1'}],
'columns': [{'field': 'id'}, {'title': 'Foo Name', 'field': 'name'}],
'type': 'Table',
}


def test_details_respect_computed_field_title():
class Foo(BaseModel):
id: int

@computed_field(title='Foo Name')
def name(self) -> str:
return f'foo{self.id}'

foos = Foo(id=1)
details = components.Details(data=foos)

# insert_assert(table.model_dump(by_alias=True, exclude_none=True))
assert details.model_dump(by_alias=True, exclude_none=True) == {
'data': {'id': 1, 'name': 'foo1'},
'fields': [{'field': 'id'}, {'title': 'Foo Name', 'field': 'name'}],
'type': 'Details',
}

0 comments on commit eb51d74

Please sign in to comment.