I'm building my first bigger database-backend with sqlalchemy and need a table to store configurations (key-value pairs). Keys are strings, values can be quite different, and I'd like to keep the variable-type. This is what I came up with:
class Configuration(Base):
__tablename__ = "configuration"
def __init__(self, *args, **kw):
if len(args) > 0:
kw['name'] = args[0]
if len(args) > 1:
kw['value'] = args[1]
try:
json.loads(kw["value"])
except Exception:
try:
kw["_value"] = json.dumps(kw["value"])
except KeyError:
pass
super().__init__(*args, **kw)
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String, CheckConstraint("name <> ''", name="check_name_not_empty"), unique=True)
_value: Mapped[str] = mapped_column(String, CheckConstraint("_value <> ''", name="check_value_not_empty"))
@property
def value(self):
return json.loads(self._value)
@value.setter
def value(self, new_value):
self._value = json.dumps(new_value)
The basic idea is to have a column '_value' that stores the value as a json-string but the user only iteracts with the value-propery so the conversion into the json-format is hidden (as long as the objects can be converted).
The init is not so nice but I wanted to support args and keyword-args.
1 Answer 1
docstrings
ctor
The __init__
constructor is entirely too automagical.
Please write at least one sentence describing what it does,
and three doctests
illustrating the three different ways to invoke it.
class
It's unclear what class invariant you're trying to preserve.
There is a relationship between _value
and value
.
You really need to explicitly state what it is,
and offer a motivating example.
Maybe you intend for it to typically be a dict[str, Any]
? Say so.
RDBMS
columns
My understanding of this is SELECT * shall offer a _value
column and no value
column.
I imagine that Author's Intent is there shall be exactly three columns.
But the ctor admits of many additional columns being passed in,
and there is no docstring guidance on what the caller should or should not do.
Primary Key
Given that name
is UNIQUE, it's unclear what value add
the synthetic id
PK is offering.
If there's some design consideration supporting it,
please write that down explicitly.