SQLAlchemy - 使用数据库列名而非属性名设置模型中的值
我有一个表格,里面有一列叫做 TS_TEST_ID
。我在用 SQLAlchemy 创建一个模型,里面有一个这样的属性:
id = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False)
我想知道有没有办法在我的模型类的实例上设置 id
,而我只知道 TS_TEST_ID
。也就是说,我只知道数据库里这一列的名字,想把它和 id
关联起来,并设置我的模型的 id
属性。我本来希望直接用 MyModel(**{'TS_TEST_ID':1})
这样做就能成功,但结果出现了以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 4, in __init__
File "C:\Python26\lib\site-packages\sqlalchemy\orm\state.py", line 111,
in initialize_instance
return manager.events.original_init(*mixed[1:], **kwargs)
File "C:\Python26\lib\site-packages\sqlalchemy\ext\declarative.py", line 1377,
in _declarative_constructor
(k, cls_.__name__))
TypeError: 'TS_TEST_ID' is an invalid keyword argument for MyModel
我也不想为模型里的每一列都定义 TS_TEST_ID = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False)
,或者定义一个叫 TS_TEST_ID
的方法来返回 id
属性。
2 个回答
0
如果你想让 __init__
方法同时处理属性和列,虽然使用一个专门的 classmethod
工厂方法看起来更整洁,但你可以用下面的实现作为一个抽象基础:
from sqlalchemy import inspect
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
def _create_col_lookup(mapper):
return {c.name: k for k, c in mapper.columns.items()}
class ColBase(Base):
__abstract__ = True
def __init__(self, *args, **kwargs):
# Create a lookup of column name -> attr key
ctoa = _create_col_lookup(inspect(self).mapper)
# Process intersecting keys
for k in ctoa.keys() & kwargs.keys():
setattr(self, ctoa[k], kwargs.pop(k))
super().__init__(*args, **kwargs)
使用上面的代码,以下的测试都能通过:
class Foo(ColBase):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
bar = Column('Baz 1')
f = Foo(**{'Baz 1': 1})
assert f.bar == 1
f = Foo(**{'bar': 1})
assert f.bar == 1
2
这看起来比实际需要的要复杂,但它确实能工作。我希望能有更简单直接的方法来做到这一点……
@staticmethod
def fromFieldHash(h):
row = MyModel()
cols = list(row.__table__._columns)
for k, v in h.iteritems():
col = find(lambda c: c.key == k, cols)
# See http://www.sqlalchemy.org/trac/wiki/06Migration#AnImportantExpressionLanguageGotcha
if col is not None:
prop = row.__mapper__._columntoproperty[col].key
setattr(row, prop, v)
return row
我用的这个 find
方法来自于最简洁的 Python 列表查找函数。