如何遍历SQLAlchemy模型定义的列?
我一直在想怎么遍历一个SQLAlchemy模型中定义的列列表。我想这样做是为了给几个模型写一些序列化和复制的方法。因为直接遍历obj.__dict__
不行,因为里面有很多特定于SQLAlchemy的东西。
有没有人知道怎么只获取下面这些的id
和desc
名字呢?
class JobStatus(Base):
__tablename__ = 'jobstatus'
id = Column(Integer, primary_key=True)
desc = Column(Unicode(20))
在这个小例子中,我可以很容易地创建一个:
def logme(self):
return {'id': self.id, 'desc': self.desc}
但我更希望有一种方法可以自动生成dict
(对于更大的对象)。
11 个回答
我知道这个问题已经有点旧了,但我最近遇到了同样的需求,想给未来的读者提供一个替代的解决方案。
正如Josh提到的,通过JobStatus.__table__.columns
可以得到完整的SQL字段名,所以你得到的不是原来的字段名id,而是jobstatus.id。这并没有那么实用。
要获取字段名的原始定义,可以查看列对象上的_data
属性,它包含了完整的数据。如果我们查看JobStatus.__table__.columns._data
,它的样子是这样的:
{'desc': Column('desc', Unicode(length=20), table=<jobstatus>),
'id': Column('id', Integer(), table=<jobstatus>, primary_key=True, nullable=False)}
从这里你可以简单地调用JobStatus.__table__.columns.keys()
,这样就能得到一个干净整洁的字段名列表:
['id', 'desc']
你可以从映射器那里获取定义好的属性列表。在你的情况下,你只需要关注 ColumnProperty 对象。
from sqlalchemy.orm import class_mapper
import sqlalchemy
def attribute_names(cls):
return [prop.key for prop in class_mapper(cls).iterate_properties
if isinstance(prop, sqlalchemy.orm.ColumnProperty)]
你可以使用下面这个函数:
def __unicode__(self):
return "[%s(%s)]" % (self.__class__.__name__, ', '.join('%s=%s' % (k, self.__dict__[k]) for k in sorted(self.__dict__) if '_sa_' != k[:4]))
这个函数会排除掉一些特别的“魔法”属性,但不会排除关系。所以基本上,它可能会加载一些依赖、父级、子级等等,这样的结果其实并不理想。
不过其实事情要简单得多,因为如果你从 Base
继承,你就会有一个 __table__
属性,这样你就可以做:
for c in JobStatus.__table__.columns:
print c
for c in JobStatus.__table__.foreign_keys:
print c
可以参考这个链接:如何从SQLAlchemy映射对象中发现表属性 - 这是一个类似的问题。
编辑者Mike:请查看一些函数,比如 Mapper.c 和 Mapper.mapped_table。如果你使用的是0.8版本及以上,还可以查看 Mapper.attrs 和相关函数。
关于 Mapper.attrs 的示例:
from sqlalchemy import inspect
mapper = inspect(JobStatus)
for column in mapper.attrs:
print column.key