【问题标题】:Accepting multiple types on an SQLAlchemy model field在 SQLAlchemy 模型字段上接受多种类型
【发布时间】:2018-11-05 09:03:10
【问题描述】:

考虑一个带有 String 字段的 SQLAlchemy 模型:

class MyModel(Base):
    name = Column(String(100))
    # ...

让这个字段接受的正确方法是什么? int 值并在保存和查询之前将它们转换为字符串 - 本质上是 str(val) ?

最终我希望所有这些都是等效的:

m = MyModel(name='123')
m = MyModel(name=123)
q = session.query(MyModel).filter_by(name='123')
q = session.query(MyModel).filter_by(name=123)

【问题讨论】:

标签: python python-3.x sqlalchemy


【解决方案1】:

我已经在 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'>

在This Answer 中,与数据类型的验证和强制有关@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'>

所有这些方法都有据可查,因此可以被认为是“正确的”。

【讨论】:

    猜你喜欢
    • 2020-08-10
    • 1970-01-01
    • 2021-06-11
    • 2021-10-17
    • 2017-08-28
    • 1970-01-01
    • 2017-11-17
    • 2016-01-25
    • 2012-03-25
    相关资源
    最近更新 更多