Skip to content

UUID (Universally Unique Identifier)

Introduction

This guide demonstrates how to implement UUID (Universally Unique Identifier) support in SQLModel, providing a robust method for creating unique identifiers across your database tables. You can read more about UUID in the official Python docs for UUID.

Prerequisites

Ensure you have the correct version of SQLModel:

  • SQLModel 0.0.20+

Adding UUID Support

Defining Models with UUID

Pydantic has support for UUIDs types.

To use UUIDs as primary keys, you need to modify your model definitions to include uuid.UUID as the type for the ID field. Here's an example for an Item model.

Info

For the database, SQLModel will use sqlalchemy.sql.sqltypes.Uuid type.

Item Model with UUID

import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None

# Code below omitted 👇
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None

# Code below omitted 👇
👀 Full file preview
import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()

Working with UUIDs

Creating Records with UUIDs

When creating an Item record, the id field will be automatically populated with a new UUID as default_factory=uuid.uuid4 is set:

# Code above omitted 👆

def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id

# Code below omitted 👇
# Code above omitted 👆

def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id

# Code below omitted 👇
👀 Full file preview
import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()

Info

We are using here uuid.uuid4 as they are safe, enough long and unique to use as a primary key

Querying Records by UUID

To query an Item by its UUID, use the following pattern:

# Code above omitted 👆

def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item

# Code below omitted 👇
# Code above omitted 👆

def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item

# Code below omitted 👇
👀 Full file preview
import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()

Deleting Records by UUID

To delete an Item using its UUID:

# Code above omitted 👆

def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")

# Code below omitted 👇
# Code above omitted 👆

def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")

# Code below omitted 👇
👀 Full file preview
import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()

Example Usage

Here's a complete example demonstrating the creation, querying, and deletion of records with UUIDs:

import uuid

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: str | None = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()
import uuid
from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine, select


class Item(SQLModel, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    title: str
    description: Optional[str] = None


def create_sample_data_and_return_id(engine) -> uuid.UUID:
    with Session(engine) as session:
        item = Item(title="Example Item", description="An example item")
        session.add(item)
        session.commit()
        session.refresh(item)
        return item.id


def get_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        return item


def delete_item_by_uuid(engine, item_id: uuid.UUID):
    with Session(engine) as session:
        item = session.exec(select(Item).where(Item.id == item_id)).one_or_none()
        session.delete(item)
        session.commit()
        print("Item deleted successfully.")


def main() -> None:
    engine = create_engine("sqlite:///database.db", echo=True)
    SQLModel.metadata.create_all(engine)

    item_id = create_sample_data_and_return_id(engine)

    item = get_item_by_uuid(engine, item_id)
    if item:
        print(f"Found item: {item.title}")

    delete_item_by_uuid(engine, item_id)


if __name__ == "__main__":
    main()

Conclusion

This guide provided a focused overview of implementing UUID support in SQLModel. By following these steps, you can ensure that your models have robust, unique identifiers, enhancing the reliability and scalability of your application.