# 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 ```