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

Fix Boolean field #336

Merged
merged 5 commits into from
Sep 24, 2022
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
4 changes: 2 additions & 2 deletions sqladmin/_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def _set_attributes_sync(self, session: Session, obj: Any, data: dict) -> Any:

if not value:
# Set falsy values to None, if column is Nullable
if not relation and column.nullable:
if not relation and column.nullable and value is not False:
value = None

setattr(obj, key, value)
Expand Down Expand Up @@ -79,7 +79,7 @@ async def _set_attributes_async(

if not value:
# Set falsy values to None, if column is Nullable
if not relation and column.nullable:
if not relation and column.nullable and value is not False:
value = None

setattr(obj, key, value)
Expand Down
10 changes: 9 additions & 1 deletion sqladmin/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,15 @@ def conv_text(
def conv_boolean(
self, model: type, prop: ColumnProperty, kwargs: Dict[str, Any]
) -> UnboundField:
return BooleanField(**kwargs)
if not prop.columns[0].nullable:
kwargs.setdefault("render_kw", {})
kwargs["render_kw"]["class"] = "form-check-input"
return BooleanField(**kwargs)

kwargs["allow_blank"] = True
kwargs["choices"] = [(True, "True"), (False, "False")]
kwargs["coerce"] = lambda v: str(v) == "True"
return SelectField(**kwargs)

@converts("Date")
def conv_date(
Expand Down
13 changes: 8 additions & 5 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@
URLType,
UUIDType,
)
from wtforms import Field, Form, StringField, TimeField
from wtforms import BooleanField, Field, Form, StringField, TimeField

from sqladmin import ModelView
from sqladmin.fields import SelectField
from sqladmin.forms import get_model_form
from tests.common import DummyData, async_engine as engine

Expand All @@ -54,7 +55,8 @@ class User(Base):
name = Column(String(32), default="SQLAdmin")
email = Column(String, nullable=False)
bio = Column(Text)
active = Column(Boolean)
active = Column(Boolean, nullable=True)
verified = Column(Boolean, nullable=False)
registered_at = Column(DateTime)
status = Column(Enum(Status))
balance = Column(Numeric)
Expand Down Expand Up @@ -98,11 +100,12 @@ async def test_model_form() -> None:
Form = await get_model_form(model=User, engine=engine)
form = Form()

assert len(form._fields) == 11
assert len(form._fields) == 12
assert form._fields["active"].flags.required is None
assert form._fields["name"].flags.required is None
assert form._fields["email"].flags.required is True

assert isinstance(form._fields["active"], SelectField)
assert isinstance(form._fields["verified"], BooleanField)
assert isinstance(form._fields["reminder"], TimeField)


Expand All @@ -123,7 +126,7 @@ async def test_model_form_only() -> None:

async def test_model_form_exclude() -> None:
Form = await get_model_form(model=User, engine=engine, exclude=["status"])
assert len(Form()._fields) == 10
assert len(Form()._fields) == 11


async def test_model_form_form_args() -> None:
Expand Down