Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect computed_field title in Details #306

Merged
merged 1 commit into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
}
Loading