48

I'm using SQLAlchemy core with a postgresql database and I would like to add the ENUM type to my table definition. According to the postgresql documentation, the ENUM type must be defined prior to the table being created:

CREATE TYPE gender_enum AS ENUM ('female', 'male');

CREATE TABLE person (
  name VARCHAR(20),
  gender gender_enum
);

The problem is when I'm creating the table definition. After reading the SQLAlchemy documentation I couldn't find any implementation examples. I've tried something like this but it didn't work:

from sqlalchemy.dialects.postgresql import ENUM

person = Table('user_profile', metadata,
    Column('name', String(20)),
    Column('gender', ENUM('female', 'male'))
);

How it must be done?

4 Answers 4

49

You need to import Enum from sqlalchemy and add a name to it. It should work like this:

from sqlalchemy import Enum

person = Table("user_profile", metadata,
    Column("name", String(20)),
    Column("gender", Enum("female", "male", name="gender_enum", create_type=False))
);
Sign up to request clarification or add additional context in comments.

6 Comments

For this to work with postgres for me, I had to from sqlalchemy.dialects.postgresql import ENUM
Well which is it? OP said postgreql.ENUM didn't work, comment says it does work. Is there a version or driver distinction that causes the discrepancy?
Why: create_type=False?
create_type isn't actually useful here - that's for sqlalchemy.dialects.postgresql.ENUM. In a nutshell - use sqlalchemy.Enum if you want to define the enum type and create it during a create_table command. If you want to use an existing type for a new table during creation, use the dialects.postgresql.ENUM one with create_type = False
In case anyone is using specific schemas, I had the same issue and I was able to solve it using from sqlalchemy import Enum and for the schema I was able to pass schema=<schema_name> to Enum. Enum type documentation: docs.sqlalchemy.org/en/13/core/…
|
40

@Tim's answer is definitely correct but I wanted to offer the way I setup my ENUMs.

In my models.py I will create the values as tuples

skill_levels = ('Zero', 'A little', 'Some', 'A lot')

Then I will create a skill_level_enum variable and assign it an ENUM class with the skill level values as args.

skill_level_enum = ENUM(*skill_levels, name="skill_level")

In my table model then I pass in the skill_level_enum

class User(db.Model):
    id = db.Column(db.Integer(), primary_key=True)
    skill_level = db.Column(skill_level_enum)

I have found this makes my code a lot cleaner and I'm able to make updates to the skill_levels at the top of my file rather than scanning my models for the right thing to update.

1 Comment

That is correct, you can define the enum once and use it wherever you need to.
14

You can use Python's native enums as the input for a column type:

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.postgresql import ENUM as pgEnum
from enum import Enum, unique

@unique
class errorTypeEnum(Enum):
    videoValidation = 'videoValidation'
    audioValidation = 'audioValidation'
    subtitleValidation = 'subtitleValidation'

db = SQLAlchemy()

class Error(db.Model):
    serviceID = db.Column(db.String(20), primary_key=True)
    timestamp = db.Column(db.DateTime, unique=False, nullable=False)
    category = db.Column(pgEnum(errorTypeEnum), unique=False, nullable=False)

Comments

4

The code below worked for me on SQLAlchemy 1.3.11 and Postgres 12.0.

You must first create the Enum type in postgres before creating the user table. This can be done directly through sql statement.

CREATE TYPE permission AS ENUM ('READ_ONLY', 'READ_WRITE', 'ADMIN', 'OWNER');

Then set up the project model

from flask_sqlalchemy import SQLAlchemy    

db = SQLAlchemy()

class User(db.Model): 
    __tablename__ = 'user'

    user_id = db.Column(db.Integer, primary_key=True)   
    username = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)
    access = db.Column(db.Enum('READ_ONLY', 'READ_WRITE', 'ADMIN', 'OWNER', name="permission"))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.