How to generate a UUID field with FastAPI, SQLalchemy, and SQLModel
Asked Answered
S

1

10

I'm struggling to get the syntax to create a UUID field when creating a model in my FastAPI application. I'm using SQLModel.

So basically, my models.py file looks like this:

from datetime import datetime
from typing import Optional
import uuid

from sqlalchemy import Column, DateTime
from sqlalchemy.dialects import postgresql as psql
from sqlmodel import SQLModel, Field


class ModelBase(SQLModel):
    """
    Base class for database models.
    """
    id: Optional[int] = Field(default=None, primary_key=True)
    created_at: datetime = Field(sa_column=Column(DateTime(timezone=True), default=datetime.utcnow))
    updated_at: datetime = Field(sa_column=Column(DateTime(timezone=True),
                                 onupdate=datetime.utcnow, default=datetime.utcnow))


class UUIDModelBase(ModelBase, table=True):
    """
    Base class for UUID-based models.
    """
    uuid: uuid.UUID = Field(sa_column=Column(psql.UUID(as_uuid=True)), default=uuid.uuid4)

The above errors out with

AttributeError: 'FieldInfo' object has no attribute 'UUID'

I also tried

id: uuid.UUID = Column(psql.UUID(as_uuid=True), default=uuid.uuid4)
TypeError: Boolean value of this clause is not defined

Also

uuid: uuid.UUID = Column(psql.UUID(as_uuid=True), default=uuid.uuid4)
AttributeError: Neither 'Column' object nor 'Comparator' object has an attribute 'UUID'

and

uuid: uuid.UUID = Field(default_factory=uuid.uuid4, index=True, nullable=False)
 AttributeError: 'FieldInfo' object has no attribute 'UUID'

You get the idea. The errors are not helping me, I just need the right syntax.

In this case, I'm not actually looking to use UUID as a primary key. And as you can tell from the imports, I'm using postgreSQL. The database is based on a postgres:12 docker image.

Stereochemistry answered 30/11, 2021 at 15:46 Comment(0)
E
18

The interpreter might be using UUID of your actual field uuid instead of the imported package. So, you can change the code as follows.

import uuid as uuid_pkg

from sqlalchemy import Field
from sqlmodel import Field

class UUIDModelBase(ModelBase):
    """
    Base class for UUID-based models.
    """
    uuid: uuid_pkg.UUID = Field(
        default_factory=uuid_pkg.uuid4,
        primary_key=True,
        index=True,
        nullable=False,
    )

Reference: https://github.com/tiangolo/sqlmodel/issues/140

Extricate answered 3/12, 2021 at 16:4 Comment(5)
Nice! That was it :)Stereochemistry
PostgreSQL v13+ also supports gen_random_uuid() so you can have server_default="gen_random_uuid()". Before this was available only as a PostgreSQL extension.Antipodes
postgresql.org/docs/13/functions-uuid.htmlAntipodes
tried this one to fix issue described here, but it didn't work. any ideas?Odiliaodille
How to use uuid7?Takeshi

© 2022 - 2024 — McMap. All rights reserved.