0

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

4

0 回答 0