使用动态映射和复杂对象查询的SQLAlchemy
我遇到了以下情况:
class MyBaseClass(object):
def __init__(self, name):
self.name = name
self.period = None
self.foo = None
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
如果在运行时需要添加一些额外的列,我们可以这样做:
my_base_class_table = Table("MyBaseClass", metadata,
Column('name', String, primary_key=True),
Column('period', DateTime),
Column('foo', Float),
)
my_base_class_table = Table("MyBaseClass", metadata, extend_existing=True)
column_list = ["value_one", "other_name", "random_XARS123"]
for col in column_list:
my_base_class_table.append_column(Column(col, Float))
create_all()
mapper(MyBaseClass, my_base_class_table)
到这里为止,我们已经有了一个功能齐全的动态表映射,并且有了扩展的列。
现在,使用sqlalchemy的ORM(对象关系映射),你可以轻松地实例化一个MyBaseClass,并修改它以反映数据库中的变化:
base_class = MyBaseClass(name="Something")
base_class.period = "2002-10-01"
并且可以使用那些列名未知的动态列:
for col in column_list:
base_class[col] = 10
session.add(base_class)
但实际上只有在你知道列名的情况下:
t_query = session.query(func.strftime('%Y-%m-%d', MyBaseClass.period),
func.sum(MyBaseClass.foo), \
func.sum(MyBaseClass.other_name*MyBaseClass.value_one))
有没有可能在不知道列名的情况下重复最后的查询(t_query
)?我已经尝试了不同的情况,但都没有成功:
func.sum(MyBaseClass[column_list[0]]*MyBaseClass.[column_list[1]])
实际上唯一有效的方法是使用扩展的文本SQL,比如:
text_query = text("SELECT strftime('%Y-%m-%d', period) as period, sum(foo) as foo, sum({0}*{1}) as bar FROM {2} ".format(column_list[0], column_list[1], "MyBaseClass")
1 个回答
2
简单的 getattr
就能解决这个问题:
t_query = session.query(func.strftime('%Y-%m-%d', getattr(MyBaseClass, "period")),
func.sum(getattr(MyBaseClass, "foo")),
func.sum(getattr(MyBaseClass, "other_name") * getattr(MyBaseClass, "value_one"))
)