You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
How to make enum column to work with SQLModel? #96
Just make sure that if you're using Alembic migration autogeneration and you require values to be stored as Enum in the database and not String, you modify the column type in the generated migration script.
Reacted by Lance Hasson, haja-k, Javad Miraftabzadeh, mohammed , Winrey, Navaneethan, Arnau, Muhammad Yaseen, Miguel Sebastián Frausto Zapata and Abdullah Tahir
Reacted by haja-k, Jonathan Vargas, Rodrigo Medina, mohammed , Alejandro Latorre, Winrey, Tran Dong, danielaRiesgo and Rida Zouga
Just make sure that if you're using Alembic migration autogeneration and you require values to be stored as Enum in the database and not String, you modify the column type in the generated migration script.
This worked for me. However, I think it would be a bit nicer if we could just specify
training_status: Enum[TrainingStatus]
or similar as the type.
Reacted by Matt Morris, mrh1997, Winrey, David McQueen, Alq and Giorgi Merebashvili
Reacted by haja-k, Winrey, Mohamed Martini and chattershuts
Just make sure that if you're using Alembic migration autogeneration and you require values to be stored as Enum in the database and not String, you modify the column type in the generated migration script.
Thanks @yasamoka This solution worked for me. Just one thing Enum on training_status: TrainingStatus = Field(sa_column=Column(Enum(TrainingStatus))) is imported from sqlmodel and Enum on TrainingStatus is imported from enum.Enum I lost some time until I realized this.
Reacted by Ramzi Sabra, Sean Rapp, Tharinda Seth Wijesekera, Noam Friedman, norayr-im, Joel Berkeley, Ahmad Sajid, Sagit Khaliullin, lexi, Daniel Gafni and 13 more
Reacted by norayr-im, Ahmad Sajid, Tanmay patil and danielaRiesgo
Just make sure that if you're using Alembic migration autogeneration and you require values to be stored as Enum in the database and not String, you modify the column type in the generated migration script.
I do not get how I should "require values to be stored as Enum" when using postgresql engine for example. Is there a flag somewhere or how does that work?
I'm getting an error which looks like sqlmodel is trying to save the enum as a string:
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input value for enum objecttypes: "type1"
I do not get how I should "require values to be stored as Enum" when using postgresql engine for example. Is there a flag somewhere or how does that work?
I'm getting an error which looks like sqlmodel is trying to save the enum as a string:
sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) invalid input value for enum objecttypes: "type1"
Here is a sample migration from a project of mine that shows how this is done. This is a migration script that changes a column from String to Enum.
"""language_fluency
Revision ID: 5342a2459462
Revises: 919490ea9497
Create Date: 2021-09-17 03:49:14.251234
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '5342a2459462'
down_revision = '919490ea9497'
branch_labels = None
depends_on = None
fluency = sa.Enum('WEAK', 'MODERATE', 'GOOD', name='fluency')
def upgrade():
fluency.create(op.get_bind())
op.alter_column('language', 'fluency', type_=fluency, postgresql_using='fluency::text::fluency')
def downgrade():
op.alter_column('language', 'fluency', type_=sqlmodel.sql.sqltypes.AutoString())
fluency.drop(op.get_bind())
do I really need a working alembic setup if I start from scratch? I can see that the table is created correctly but for some reason sqlmodel / psycopg2==2.9.3 are creating wrong queries. This is what the db looks like:
Table "public.items"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
type | itemtypes | | |
id | uuid | | not null |
name | character varying | | not null |
Does alembic change how sqlmodel/sqlalchemy generates statements and passes the parameters to that?
What do you mean by starting from scratch? Do you mean that you have an existing database and you have yet to setup Alembic for migrations? If so, then no, you do not need a working alembic setup if you can manually define your column type correctly on the database schema itself directly.
Alembic doesn't change anything related to how SQLModel / SQLAlchemy generates statements. Alembic compares your existing database against the schema it reads from your code and generates schema migrations based on that. Regardless of whether those migrations are applied, it is SQLAlchemy that ultimately generates statements based on your models and tables as defined in your code. If there is still a mismatch between your actual database and the models / tables you have defined, then you get an error.
From scratch I mean that I create an empty postgresql server and use the SQLModel.metadata.create_all(engine) to create tables. I got this working with mysql so I guess the main issue I'm having is that sqlmodel does not create the postgresql enum correctly. Postgres shows
From scratch I mean that I create an empty postgresql server and use the SQLModel.metadata.create_all(engine) to create tables. I got this working with mysql so I guess the main issue I'm having is that sqlmodel does not create the postgresql enum correctly. Postgres shows
Hello, @alhoo I had the same problem and I noticed that the error happens if the table you are adding the new enum column already exists. In my case, I deleted the table and created a new migration and it worked, new types were created. I am not sure why alembic does not create a new enum type automatically on existing tables. This is not the best solution but works.
import enum
from sqlalchemy import (Column, Integer)
from sqlalchemy_utils import ChoiceType
from sqlmodel import SQLModel, Field
class LightType(enum.IntEnum):
off = 0
on = 1
flashing = 2
class Events(SQLModel, table=True):
green: LightType = Field(sa_column=Column(ChoiceType(LightType, impl=Integer()), nullable=False))
Reacted by haja-k, Eloy Adonis Colell, Honglei, Khyn Antoque, Adrián Constante, hirousto, eshine996, rysson, Humphrey Ahn and Priyansh2001here
class NotificationPriority(Enum):
LOW = "LOW"
MEDIUM = "MEDIUM"
HIGH = "HIGH"
CRITICAL = "CRITICAL"
....
File "/workspaces/api/src/n0tifs/models.py", line 255, in Notification
priority: NotificationPriority = Field(sa_type=Enum(NotificationPriority))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/vscode/.local/lib/python3.12/site-packages/sqlalchemy/sql/sqltypes.py", line 1397, in __init__
self._enum_init(enums, kw)
File "/home/vscode/.local/lib/python3.12/site-packages/sqlalchemy/sql/sqltypes.py", line 1427, in _enum_init
self._default_length = length = max(len(x) for x in self.enums)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/vscode/.local/lib/python3.12/site-packages/sqlalchemy/sql/sqltypes.py", line 1427, in <genexpr>
self._default_length = length = max(len(x) for x in self.enums)
^^^^^^
TypeError: object of type 'type' has no len()
UseCase: I want to have an enum in python and the keys to use in Python should be UPPERCASE. The values should be different in the database and I want to reference them. Should be done with SQLModel and alembic.
Solution
importenumfromsqlmodelimportINTEGER, Column, Enum, Field, SQLModeldefenum_values(enum_class: type[enum.Enum]) ->list:
"""Get values for enum."""return [status.valueforstatusinenum_class]
# watch out which enum you use. This should be the python enumclassAlive(enum.Enum):
NO="no"YES="yes"# here the database representation, where a column `alive` will be created with - the values: [no, yes] of the enum, # instead of the keys `NO,YES`classAliveDB(SQLModel, table=True):
__tablename__="Alive"id: int|None=Field(
sa_column=Column(
name="alive_id",
nullable=False,
type_=INTEGER,
primary_key=True,
default=None,
)
)
alive: Alive=Field(
sa_column=Column(
name="alive",
nullable=False,
type_=Enum(Alive, values_callable=enum_values),
)
)
Reacted by Christian-Manuel Butzke, Can Burak Sofyalıoğlu, Ted Li, Precious , Mai Chân Chính, keijay and Iks
Activity
[-]How to make enum column to work in with SQLModel?[/-][+]How to make enum column to work with SQLModel?[/+]yasamoka commentedon Sep 16, 2021
training_status: TrainingStatus = Field(sa_column=Column(Enum(TrainingStatus)))Just make sure that if you're using Alembic migration autogeneration and you require values to be stored as
Enumin the database and notString, you modify the column type in the generated migration script.JLHasson commentedon Nov 20, 2021
This worked for me. However, I think it would be a bit nicer if we could just specify
or similar as the type.
Enum fixes (typing and inheritance)
haja-k commentedon Dec 8, 2021
Thank you!
vargasjona commentedon May 17, 2022
Thanks @yasamoka This solution worked for me. Just one thing Enum on training_status: TrainingStatus = Field(sa_column=Column(Enum(TrainingStatus))) is imported from sqlmodel and Enum on TrainingStatus is imported from enum.Enum I lost some time until I realized this.
alhoo commentedon May 31, 2022
I do not get how I should "require values to be stored as
Enum" when using postgresql engine for example. Is there a flag somewhere or how does that work?I'm getting an error which looks like sqlmodel is trying to save the enum as a string:
yasamoka commentedon May 31, 2022
Here is a sample migration from a project of mine that shows how this is done. This is a migration script that changes a column from String to Enum.
alhoo commentedon May 31, 2022
do I really need a working alembic setup if I start from scratch? I can see that the table is created correctly but for some reason sqlmodel / psycopg2==2.9.3 are creating wrong queries. This is what the db looks like:
Does alembic change how sqlmodel/sqlalchemy generates statements and passes the parameters to that?
yasamoka commentedon May 31, 2022
What do you mean by starting from scratch? Do you mean that you have an existing database and you have yet to setup Alembic for migrations? If so, then no, you do not need a working alembic setup if you can manually define your column type correctly on the database schema itself directly.
Alembic doesn't change anything related to how SQLModel / SQLAlchemy generates statements. Alembic compares your existing database against the schema it reads from your code and generates schema migrations based on that. Regardless of whether those migrations are applied, it is SQLAlchemy that ultimately generates statements based on your models and tables as defined in your code. If there is still a mismatch between your actual database and the models / tables you have defined, then you get an error.
alhoo commentedon May 31, 2022
From scratch I mean that I create an empty postgresql server and use the
SQLModel.metadata.create_all(engine)to create tables. I got this working withmysqlso I guess the main issue I'm having is thatsqlmodeldoes not create the postgresql enum correctly. Postgres showsMaybe alembic works by correcting that enum.
yasamoka commentedon May 31, 2022
The Alembic migration I showed you was not autogenerated. It was written manually (
alembic revision -m "message").vargasjona commentedon Jun 2, 2022
Hello, @alhoo I had the same problem and I noticed that the error happens if the table you are adding the new enum column already exists. In my case, I deleted the table and created a new migration and it worked, new types were created. I am not sure why alembic does not create a new enum type automatically on existing tables. This is not the best solution but works.

malf2 commentedon Sep 22, 2022
The following solution worked fine for me:
2 remaining items
haja-k commentedon Nov 15, 2022
Thanks for the help everyone :)
Pk13055 commentedon Feb 23, 2023
@jonra1993 Using this approach how would you set a default value, either/both at the database level and sqlmodel level
EDIT: Got it, you can just set a default inside the
Field(), ie,Field(default=SomeEnum.foo)turangojayev commentedon Jul 26, 2023
The solution provided here doesn't automatically create the enum type in case it is missing with postgresql, at least with my setting:
I am calling
createmanually (Enum(TrainingStatus).create(engine)) to fix thischristianholland commentedon Jul 27, 2023
@turangojayev could you please provide more details for your proposed fix? E.g. when and where exactly do you call
create?turangojayev commentedon Aug 17, 2023
sorry for late response, well, I basically do
tjeaneric commentedon Nov 14, 2023
If you want enum types to be recognized by alembic, do the following.
Installation
pip install alembic-postgresql-enum or poetry add alembic-postgresql-enumAdd import to envy.py
import alembic_postgresql_enumWhen you update enum types, alembic will detect the changes and automatically generate migrations.
dipsx commentedon Apr 4, 2024
Can we change the scheme of where the Enum type is stored?
sunkunxi commentedon Jul 3, 2024
I prefre to use
sa_type:bashtian-fr commentedon Oct 2, 2024
this create the following error for me:
Mekacher-Anis commentedon Oct 19, 2024
@bashtian-fr I have the same issue SQLModel version 0.0.21
Tyskiep99 commentedon Oct 20, 2024
Hey there, I solved it by doing the following:
Note, that the enum class extend str AND Enum, which is from the
enummodule, while I use SQLModelEnumfor the columnweitzj commentedon Jan 25, 2025
To summarize what helped me:
UseCase: I want to have an enum in python and the keys to use in Python should be UPPERCASE. The values should be different in the database and I want to reference them. Should be done with SQLModel and alembic.
Solution
kroawen commentedon Dec 10, 2025
sunkunxi commentedon Jan 31, 2026
Yes! I forgot to mention, use
Enumfrom sqlalchemy, not from pythonenum.I also have an advance solution! That what I am doing in my project. Sqlalchemy has
TypeDecoratorwhich you can use to customize a Enum Type.See my pr related to IntEnum column: #1337
Also, there is another pr about how to have a JSON type column: #1324
You can easily have your own StrEnum by using sqlalchemy TypeDecorator