迭代sqlalchemy模型定义列的方法?

2024-05-12 21:05:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在尝试如何遍历SQLAlchemy模型中定义的列列表。我需要它来编写一些序列化和复制方法到几个模型。我不能只遍历obj.__dict__,因为它包含许多SA特定的项。

有没有人知道从下面得到iddesc名称的方法?

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(用于较大的对象)。


Tags: 方法模型self名称idobj列表序列化
3条回答

我意识到这是一个老问题,但我遇到了同样的要求,我想为未来的读者提供一个替代的解决方案。

正如Josh所指出的,完整的SQL字段名将由JobStatus.__table__.columns返回,因此您将得到jobstatus.id而不是原始字段名。没那么有用。

获取最初定义的字段名列表的解决方案是查看包含完整数据的column对象的_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._data.keys(),这给了您一个很好的、干净的列表:

['id', 'desc']

您可以使用以下函数:

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]))

它将排除SAmagic属性,但不排除关系。所以基本上它可能会加载依赖项、父项、子项等,这绝对是不可取的。

但实际上要容易得多,因为如果从Base继承,就有一个__table__属性,这样就可以:

for c in JobStatus.__table__.columns:
    print c

for c in JobStatus.__table__.foreign_keys:
    print c

How to discover table properties from SQLAlchemy mapped object-类似问题。

由Mike编辑:请参阅Mapper.cMapper.mapped_table等函数。如果使用0.8或更高版本,请参见Mapper.attrs和相关函数。

例如Mapper.attrs

from sqlalchemy import inspect
mapper = inspect(JobStatus)
for column in mapper.attrs:
    print column.key

可以从映射器中获取已定义属性的列表。对于您的情况,您只对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)]

相关问题 更多 >