Skip to content

Commit

Permalink
Add some field props from SQLAlchemy models (#764)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamsorcerer committed Jul 31, 2023
1 parent d8ab462 commit 61e0c0d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
11 changes: 10 additions & 1 deletion aiohttp_admin/backends/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,24 @@ def __init__(self, db: AsyncEngine, model_or_table: Union[sa.Table, type[Declara
"target": key.column.name}
else:
field, inp, props = get_components(c.type)
props["source"] = c.name

props["source"] = c.name
if isinstance(c.type, sa.Enum):
props["choices"] = tuple({"id": e.value, "name": e.name}
for e in c.type.python_type)

length = getattr(c.type, "length", 0)
if length is None or length > 31:
props["fullWidth"] = True
if length is None or length > 127:
props["multiline"] = True

if isinstance(c.default, sa.ColumnDefault):
props["placeholder"] = c.default.arg

if c.comment:
props["helperText"] = c.comment

self.fields[c.name] = comp(field, props)
if c.computed is None:
# TODO: Allow custom props (e.g. disabled, multiline, rows etc.)
Expand Down
30 changes: 25 additions & 5 deletions tests/test_backends_sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ class TestModel(base): # type: ignore[misc,valid-type]
assert r.name == "dummy"
assert r.primary_key == "id"
assert r.fields == {"id": comp("NumberField", {"source": "id"}),
"num": comp("TextField", {"source": "num"})}
"num": comp("TextField", {"source": "num", "fullWidth": True,
"multiline": True})}
# Autoincremented PK should not be in create form
assert r.inputs == {
"id": comp("NumberInput", {"source": "id", "validate": [func("required", ())]})
| {"show_create": False},
"num": comp("TextInput", {"source": "num", "validate": [func("required", ())]})
"num": comp("TextInput", {
"source": "num", "fullWidth": True, "multiline": True,
"validate": [func("required", ())]})
| {"show_create": True}
}

Expand All @@ -66,6 +69,21 @@ def test_table(mock_engine: AsyncEngine) -> None:
}


def test_extra_props(base: type[DeclarativeBase], mock_engine: AsyncEngine) -> None:
class TestModel(base): # type: ignore[misc,valid-type]
__tablename__ = "dummy"
id: Mapped[int] = mapped_column(primary_key=True)
num: Mapped[str] = mapped_column(sa.String(128), comment="Foo", default="Bar")

r = SAResource(mock_engine, TestModel)
assert r.fields["num"]["props"] == {
"source": "num", "fullWidth": True, "multiline": True, "placeholder": "Bar",
"helperText": "Foo"}
assert r.inputs["num"]["props"] == {
"source": "num", "fullWidth": True, "multiline": True, "placeholder": "Bar",
"helperText": "Foo", "validate": [func("maxLength", (128,))]}


async def test_binary(
base: DeclarativeBase, aiohttp_client: Callable[[web.Application], Awaitable[TestClient]],
login: _Login
Expand Down Expand Up @@ -243,19 +261,21 @@ async def test_nonid_pk(base: type[DeclarativeBase], mock_engine: AsyncEngine) -
class TestModel(base): # type: ignore[misc,valid-type]
__tablename__ = "test"
num: Mapped[int] = mapped_column(primary_key=True)
other: Mapped[str]
other: Mapped[str] = mapped_column(sa.String(64))

r = SAResource(mock_engine, TestModel)
assert r.name == "test"
assert r.primary_key == "num"
assert r.fields == {
"num": comp("NumberField", {"source": "num"}),
"other": comp("TextField", {"source": "other"})
"other": comp("TextField", {"source": "other", "fullWidth": True})
}
assert r.inputs == {
"num": comp("NumberInput", {"source": "num", "validate": [func("required", ())]})
| {"show_create": False},
"other": comp("TextInput", {"source": "other", "validate": [func("required", ())]})
"other": comp("TextInput", {
"fullWidth": True, "source": "other",
"validate": [func("required", ()), func("maxLength", (64,))]})
| {"show_create": True}
}

Expand Down

0 comments on commit 61e0c0d

Please sign in to comment.