Skip to content
2 changes: 1 addition & 1 deletion sqladmin/pretty_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async def _base_export_cell(
"""
if name in model_view._relation_names:
if isinstance(value, list):
cell_value = ",".join(formatted_value)
cell_value = ",".join(str(item) for item in formatted_value)
Comment thread
mmzeynalli marked this conversation as resolved.
else:
cell_value = formatted_value

This comment was marked as resolved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keyed collections (attribute_keyed_dict) aren't list/tuple/set/str, so they
fall through here and reach the CSV as a Python repr:

1,"Main St,Second St","alpha,vip","{'sku-1': <__main__.Item object at 0x7f55d58e03d0>, ...}"

Two runs of the same export over the same rows:

run 1: ...<__main__.Item object at 0x7f55d58e03d0>...
run 2: ...<__main__.Item object at 0x7fe63fae0390>...

Which is the opposite of the comment three lines up — sets became reproducible in
the same commit that left mappings not reproducible. It also leaks the module path
and ignores __str__ on the related model, which every other branch honours.

9a3e5a6 had this right via Iterable (it produced sku-1,sku-2). Narrowing away
from Iterable was a sound instinct, but could we name dict rather than let it
fall through?

elif isinstance(formatted_value, dict):
    cell_value = ",".join(str(item) for item in formatted_value.values())

else:
Expand Down
26 changes: 26 additions & 0 deletions tests/test_pretty_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,32 @@ class UserAdmin(ModelView, model=User):
assert values[1] == "John Doe"
assert values[2] == "TRUE"

async def test_get_export_row_values_with_relationship(self):
class UserAdmin(ModelView, model=User):
column_list = ["id", "name", "addresses"]
session_maker = session_maker
is_async = False

with session_maker() as session:
user = User(id=1, name="John Doe", email="john@example.com")
session.add(user)
session.add(Address(id=1, street="Main St", user_id=1))
session.add(Address(id=2, street="Second St", user_id=1))
session.commit()
user = session.get(User, 1)

model_view = UserAdmin()
column_names = ["id", "name", "addresses"]

values = await PrettyExport._get_export_row_values(
model_view, user, column_names
)

assert len(values) == 3
assert values[0] == 1
assert values[1] == "John Doe"
assert values[2] == ",".join(str(address) for address in user.addresses)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add __str__ to Adress


async def test_get_export_row_values_with_none_values(self):
class UserAdmin(ModelView, model=User):
column_list = ["id", "name", "email"]
Expand Down
Loading