python - 在 SQLAlchemy 模型字段上接受多种类型
问题描述
考虑一个带有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)
解决方案
我已经在 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事件系统来拦截设置在检测属性上的数据并执行操作。
另一种方法是使用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'>
所有这些方法都有据可查,因此可以被认为是“正确的”。
推荐阅读
- c# - 使用 Ultramapper 映射对象时出错
- angular - 从 Linux 创建 ASP.NET Core 3.0 Angular Wep 应用程序映像
- bokeh - 散景服务器无法识别
- flutter - Flutter:DateTimeField 手动编辑问题
- ios - 使在 Xcode 11 中创建的项目向后兼容
- python - 添加公式后使用 pandas / xslxwriter 对列进行排序
- git - go-git:是否可以对原始分支执行硬重置?
- braintree - 如何在 UI 中的 Braintree 的 dropin 中编辑卡片?
- python - python:如何不断更新QGridLayout中的按钮
- c# - System.ArgumentOutOfRangeException: '索引超出范围。从一个列表复制到另一个