SQLAlchemy 对声明类的内省
我正在写一个小工具,用来从MySQL数据库导出数据,并进行一些简单的数据转换——主要是更改字段名称。我的脚本现在运行得很好,但我需要在类声明中描述我的模型两次——一次是在类的定义里,另一次是作为一个字段名称的列表来遍历。
我想弄清楚如何使用反射来识别行对象上的属性,这些属性是列的访问器。下面的代码几乎完美地工作:
for attr, value in self.__class__.__dict__.iteritems():
if isinstance(value, sqlalchemy.orm.attributes.InstrumentedAttribute):
self.__class__._columns.append(attr)
但我的多对多关系的访问器也是sqlalchemy.orm.attributes.InstrumentedAttribute的实例,我需要跳过这些。在检查类字典时,有没有办法区分这两者呢?
我找到的大部分关于sqlalchemy反射的文档都涉及到查看metadata.table,但由于我在重命名列,这些数据并不是简单可映射的。
3 个回答
一个 InstrumentedAttribute
实例有一个叫做 impl
的属性,实际上这个属性可以是 ScalarAttributeImpl
、ScalarObjectAttributeImpl
或者 CollectionAttributeImpl
其中之一。
我不太确定这个判断有多脆弱,但我只是检查它是哪一种,以确定这个实例最终会返回一个列表还是一个单独的对象。
每个被映射的实体都有一个叫做 columns
的属性,这个属性里面包含了所有的列定义。比如说,如果你有一个声明式的类 User
,你可以通过 User.__mapper__
来访问这个映射器,然后用下面的方式来获取列的信息:
list(User.__mapper__.columns)
每一列都有几个属性,比如 name
(这个名字可能和映射的属性 key
不一样)、nullable
、unique
等等……
我还是想看到这个问题的答案,不过我通过改变关系访问器的名字来解决了这个问题(比如用'_otherentity'代替'otherentity'),然后根据名字进行筛选。这样做对我来说效果很好。