Tables are database objects that contain all the data in a database.
In tables, data is logically organized in a row-and-column format similar to a spreadsheet. Each row represents a unique record, and each column represents a field in the record.
To create a table make a class that inherits from rx.Model
.
The following example shows how to create a table called User
.
class User(rx.Model, table=True):
username: str
email: str
The table=True
argument tells Reflex to create a table in the database for
this class.
By default, Reflex will create a primary key column called id
for each table.
However, if an rx.Model
defines a different field with primary_key=True
, then the
default id
field will not be created. A table may also redefine id
as needed.
It is not currently possible to create a table without a primary key.
SQLModel automatically maps basic python types to SQLAlchemy column types, but
for more advanced use cases, it is possible to define the column type using
sqlalchemy
directly. For example, we can add a last updated timestamp to the
post example as a proper DateTime
field with timezone.
import datetime
import sqlmodel
import sqlalchemy
class Post(rx.Model, table=True):
...
update_ts: datetime.datetime = sqlmodel.Field(
default=None,
sa_column=sqlalchemy.Column(
"update_ts",
sqlalchemy.DateTime(timezone=True),
server_default=sqlalchemy.func.now(),
),
)
To make the Post
model more usable on the frontend, a dict
method may be provided
that converts any fields to a JSON serializable value. In this case, the dict method is
overriding the default datetime
serializer to strip off the microsecond part.
class Post(rx.Model, table=True):
...
def dict(self, *args, **kwargs) -> dict:
d = super().dict(*args, **kwargs)
d["update_ts"] = self.update_ts.replace(microsecond=0).isoformat()
return d