how to use Enum types with SqlModel, and alembic
Asked Answered
H

1

7

I'm trying to find a way to get SqlModel and Alembic play nice together. My goal is to not have to hand-edit the auto-generated alembic migrations.

Here's my model class:

class SongBase(SQLModel):
    name: str
    artist: str
    label: str = Field(index=False)
    year: Optional[int] = None


class Song(SongBase, table=True):
    id: int = Field(default=None, primary_key=True, nullable=False)

After creating the initial migration etc, I add my enum. This is the closest I've come to something that works, after digging thru https://github.com/tiangolo/sqlmodel/issues?q=is%3Aissue+is%3Aopen+enum :

class SongType(enum.Enum):
    Rock = "Rock"
    Ballad = "Ballad"


class SongBase(SQLModel):
    name: str
    artist: str
    label: str = Field(index=False)
    song_type: SongType = Field(
        sa_column=Column(
            Enum(SongType),
            default=None,
            nullable=True,
            index=False
        )
    )
    year: Optional[int] = None


class Song(SongBase, table=True):
    id: int = Field(default=None, primary_key=True, nullable=False)

The generated alembic migration from adding the song_type field looks like this:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('song', sa.Column('song_type', sa.Enum('Rock', 'Ballad', name='songtype'), nullable=True))
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('song', 'song_type')
    # ### end Alembic commands ###

From what I can see this resembles the documentation I've found on how to make sqlalchemy and alembic work with migrations. However, when I attempt to apply this to my database, it fails:

2021-11-07 14:13:59.425 UTC [150] LOG:  execute __asyncpg_stmt_9__: ALTER TABLE song ADD COLUMN song_type songtype
2021-11-07 14:13:59.425 UTC [150] ERROR:  type "songtype" does not exist at character 39

Relevant parts of my package dependency tree:

╰─ pipenv graph
alembic==1.7.4
  - Mako [required: Any, installed: 1.1.5]
    - MarkupSafe [required: >=0.9.2, installed: 2.0.1]
  - SQLAlchemy [required: >=1.3.0, installed: 1.4.26]
    - greenlet [required: !=0.4.17, installed: 1.1.2]
asyncpg==0.24.0
fastapi==0.70.0
  - pydantic [required: >=1.6.2,<2.0.0,!=1.8.1,!=1.8,!=1.7.3,!=1.7.2,!=1.7.1,!=1.7, installed: 1.8.2]
    - typing-extensions [required: >=3.7.4.3, installed: 3.10.0.2]
  - starlette [required: ==0.16.0, installed: 0.16.0]
    - anyio [required: >=3.0.0,<4, installed: 3.3.4]
      - idna [required: >=2.8, installed: 3.3]
      - sniffio [required: >=1.1, installed: 1.2.0]
sqlmodel==0.0.4
  - pydantic [required: >=1.8.2,<2.0.0, installed: 1.8.2]
    - typing-extensions [required: >=3.7.4.3, installed: 3.10.0.2]
  - SQLAlchemy [required: >=1.4.17,<1.5.0, installed: 1.4.26]
    - greenlet [required: !=0.4.17, installed: 1.1.2]
  - sqlalchemy2-stubs [required: Any, installed: 0.0.2a19]
    - typing-extensions [required: >=3.7.4, installed: 3.10.0.2]

I know that I can hand-edit my migration to look something like this:

"""label

Revision ID: 12e8618deb97
Revises: c7350c7c7282
Create Date: 2021-11-07 15:21:06.927365

"""
from alembic import op
import sqlalchemy as sa
import sqlmodel
from sqlalchemy.dialects import postgresql
from app.models import SongType


# revision identifiers, used by Alembic.
revision = '12e8618deb97'
down_revision = 'c7350c7c7282'
branch_labels = None
depends_on = None


def upgrade():
    song_type = postgresql.ENUM(SongType, name="song_type")
    song_type.create(op.get_bind(), checkfirst=True)
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('song', sa.Column('song_type', song_type, nullable=True))
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('song', 'song_type')
    # ### end Alembic commands ###

...but my goal is to see if I can make alembic correctly autogenerate the migration - especially since the error doesn't occur until I attempt to apply the migration I hope to be able to make this safer.

I'd be very interested in any pointers on how to make this work

Heteroclite answered 7/11, 2021 at 14:17 Comment(3)
Hello, I have the same problem did you find a way to make auto migrations works as expected.Affirmative
no. We switched to piccolo orm (piccolo-orm.com) instead.Heteroclite
I could make it work, but it was needed to delete the table that required using the enum column so the new enum type was automatically created. The problem was my last migrations.Affirmative
I
0

Installing alembic-postgresql-enum should achieve what you are looking for.

Incarnate answered 30/5 at 7:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.