Я тестировал на MySQL, и ваш оригинальный код работает так:
class MyModel(Base):
__tablename__ = 'mymodel'
id = Column(Integer, primary_key=True)
name = Column("name", String(100))
if __name__ == '__main__':
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
s = Session()
new_obj = MyModel(name=123)
print(type(new_obj.name)) # <class 'int'>
s.add(new_obj)
s.commit()
s.close()
s = Session()
obj = s.query(MyModel).filter(MyModel.name == 123).one() # query with integer value
print(obj.name, type(obj.name)) # 123 <class 'str'>
В Этот ответ , относящийся к проверке и приведению типов данных @zzzeek, говорит, что sqlalchemy:
... относится к базе данных DBAPI / как к лучшему и наиболее эффективному источнику
валидации и приведения значений.
В этом ответе также подробно описан один способ использования системы SQLAlchemy Event для перехвата данных, установленных в инструментированных атрибутах, и выполнения каких-либо действий.
Другим способом будет использование декоратора hybrid_property
и связанного с ним setter
для выполнения действий по присвоению значений атрибутам по мере их установки. Он обрабатывает как новые объекты, так и запросы:
from sqlalchemy.ext.hybrid import hybrid_property
class MyModel(Base):
__tablename__ = 'mymodel'
id = Column(Integer, primary_key=True)
name_ = Column("name", String(100))
@hybrid_property
def name(self):
return self.name_
@name.setter
def name(self, val):
self.name_ = str(val)
if __name__ == '__main__':
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
s = Session()
new_obj = MyModel(name=123)
print(type(new_obj.name)) # <class 'str'>
s.add(new_obj)
s.commit()
s.close()
s = Session()
obj = s.query(MyModel).filter(MyModel.name == 123).one() # query with integer value
print(obj.name, type(obj.name)) # 123 <class 'str'>
Все эти методы хорошо документированы и поэтому могут считаться «правильными».