SqlAlchemy db.Enum: How to detect it and retrieve the values

Viewed 61

I have a function to add a column to a model:

def col(_type, label = "", **kwargs):
    c = db.Column(_type, **kwargs)
    c.info = {"label":label, "type":""}
    return c
    

I use it like:

    # Job Type
    class JTEnum(enum.Enum):
       full = "ﺖﻣﺎﻣ ﻮﻘﺗ"
       part_time = "ﻦﯿﻤﻫ ﻮﻘﺗ"
       project = "ﭖﺭﻭﮋﻫ ﺎﯾ"

    jobtype = col(db.Enum(JTEnum), "ﻥﻮﻋ ﺶﻐﻟ", unique=False,
            nullable=False,
            default=JTEnum.full.name)
    jobtype.info["choices"] = [(i.name, i.value) for i in JTEnum]

I call the col function for various columns. I would like to put the last line inside this function and it can be called on Enum type and fill the choices something like:

def col(_type, label = "", **kwargs):
    c = db.Column(_type, **kwargs)
    c.info = {"label":label, "type":""}
    if isinstance(_type, db.Enum):
       c.info["choices"] = [(i.name, i.value) for i in _type]
    return c

However, it gives the error:

TypeError: 'Enum' object is not iterable
2 Answers

The first issue I'm seeing in your code is that you default to JTEnum.full.name, which should be the Enum element not its name, then you need to iterate the underlying Enum class of the SQLAlchemy Enum.

import enum

import sqlalchemy as db


class JTEnum(enum.Enum):
    full = "ﺖﻣﺎﻣ ﻮﻘﺗ"
    part_time = "ﻦﯿﻤﻫ ﻮﻘﺗ"
    project = "ﭖﺭﻭﮋﻫ ﺎﯾ"


def col(_type, label="", **kwargs):
    c = db.Column(_type, **kwargs)
    c.info = {"label": label, "type": ""}
    if isinstance(_type, db.Enum):
        c.info["choices"] = [(i.name, i.value) for i in _type.enum_class]
    return c


c = col(
    db.Enum(JTEnum),
    "ﻥﻮﻋ ﺶﻐﻟ",
    unique=False,
    nullable=False,
    default=JTEnum.full,
)

print(c.info)

# {'label': 'ﻥﻮﻋ ﺶﻐﻟ',
# 'type': '',
# 'choices': [('full', 'ﺖﻣﺎﻣ ﻮﻘﺗ'),
#  ('part_time', 'ﻦﯿﻤﻫ ﻮﻘﺗ'),
#  ('project', 'ﭖﺭﻭﮋﻫ ﺎﯾ')]}

_type which is db.Enum is not iterable. You may refer to _type.enum_class like that:

def col(_type, label = "", **kwargs):
    c = db.Column(_type, **kwargs)
    c.info = {"label":label, "type":""}
    if isinstance(_type, db.Enum):
       c.info["choices"] = [(i.name, i.value) for i in _type.enum_class]
    return c
Related