reflex/docs/database/tables.md
2024-02-26 17:18:28 +01:00

71 lines
2.0 KiB
Markdown

# Tables
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.
## Creating a Table
To create a table make a class that inherits from `rx.Model`.
The following example shows how to create a table called `User`.
```python
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.
### Primary Key
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.
## Advanced Column Types
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.
```python
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.
```python
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
```