Я хочу использовать тип данных Python IntFlag
в приложении. В таблице базы данных доступен только тип Integer
. Чтобы обеспечить обмен данными между приложением и БД, я использую Integer TypeDecorator из SQLalchemy.
База данных уже существует и использует MariaDB. Далее вниз sqlite используется для облегчения подражания примеру.
from enum import IntFlag, auto
import sqlalchemy as sa
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base
class IntegerIntFlag(sa.types.TypeDecorator):
impl = sa.Integer
def __init__(self, intflagtype, *args, **kwargs):
super().__init__(*args, **kwargs)
self._intflagtype = intflagtype
def process_bind_param(self, value, dialect):
return value.value
def process_result_value(self, value, dialect):
return self._intflagtype(value)
class Dog(IntFlag):
Puppy = auto()
Medium = auto()
Old = auto()
TailWag = auto()
Bark = auto()
Run = auto()
Hunt = auto()
Sleep = auto()
CatsLike = auto()
CatsDislike = auto()
engine = sa.create_engine('sqlite:///:memory:')
session = sa.orm.sessionmaker(bind=engine)()
Base = declarative_base()
class DogTbl(Base):
__tablename__ = 'dogs'
Id = sa.Column('id', sa.Integer, primary_key=True)
Name = sa.Column('name', sa.String)
State = sa.Column('state', IntegerIntFlag(Dog))
Base.metadata.create_all(engine)
session.add(DogTbl(Name='dogA', State=Dog.Puppy))
session.add(DogTbl(Name='dogB', State=Dog.Medium))
session.add(DogTbl(Name='dogC', State=Dog.Old))
session.commit()
engine.execute(sa.text('insert into dogs values(4, "dogD", 4+16+512);'))
for dog in session.query(DogTbl):
print(dog.Name, ':', dog.State, '(', dog.State.value, ')')
Результат печати должен выглядеть следующим образом:
dogA : Dog.Puppy ( 1 )
dogB : Dog.Medium ( 2 )
dogC : Dog.Old ( 4 )
dogD : Dog.CatsDislike|Bark|Old ( 532 )
Столбец state
типа Integer в таблице dogs
возвращает тип данных Python IntFlag правильно.
Фильтрация записей, которые имеют только 1 статусную запись, проста:
qry = session.query(DogTbl).filter(DogTbl.State == Dog.Puppy).first()
Но как мне отфильтровать старых собак, которые тоже лают?
Это, конечно, только пример. Класс IntFlag Dog
может быть расширен по желанию.
Я не могу ответить на вопрос, как несколько записей Dog
применяются к таблице для фильтрации. - Любая подсказка приветствуется.