Python 迭代sqlalchemy模型的方法';定义了哪些列?

Python 迭代sqlalchemy模型的方法';定义了哪些列?,python,sqlalchemy,Python,Sqlalchemy,我一直在试图找出如何迭代SQLAlchemy模型中定义的列列表。我想要它来编写一些序列化并将方法复制到几个模型中。我不能只迭代obj.\uuu dict\uuu,因为它包含许多SA特定的项 有人知道从下面的列表中获取id和desc名称的方法吗 class JobStatus(Base): __tablename__ = 'jobstatus' id = Column(Integer, primary_key=True) desc = Column(Unicode(20)

我一直在试图找出如何迭代SQLAlchemy模型中定义的列列表。我想要它来编写一些序列化并将方法复制到几个模型中。我不能只迭代
obj.\uuu dict\uuu
,因为它包含许多SA特定的项

有人知道从下面的列表中获取
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的东西(对于较大的对象)。

您可以从映射器中获得已定义属性的列表。对于您的情况,您只对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]))
它将排除SA magic属性,但不会排除关系。因此,基本上它可能会加载依赖项、家长、孩子等,这绝对是不可取的

但实际上要容易得多,因为如果从
Base
继承,则有一个
\uuuuu table\uuuuu
属性,因此可以执行以下操作:

for c in JobStatus.__table__.columns:
    print c

for c in JobStatus.__table__.foreign_keys:
    print c
见-类似问题

Mike编辑:请查看和等功能。如果使用0.8及更高版本,请参见和相关函数

例如:


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

正如Josh所指出的,完整的SQL字段名将由
JobStatus.\uuuu table\uuuu.columns
返回,因此您将获得的不是原始字段名id,而是JobStatus.id。没有它可能的那么有用

获取最初定义的字段名列表的解决方案是查看包含完整数据的column对象上的
\u data
属性。如果我们查看
JobStatus.\uuuuuu table\uuuuu.columns.\u data
,它看起来是这样的:

{'desc': Column('desc', Unicode(length=20), table=<jobstatus>),
 'id': Column('id', Integer(), table=<jobstatus>, primary_key=True, nullable=False)}
class JobStatus(Base):

    ...

    def __iter__(self):
        values = vars(self)
        for attr in self.__mapper__.columns.keys():
            if attr in values:
                yield attr, values[attr]

    def logme(self):
        return dict(self)

self.\uuuuu table\uuuuu.columns
将“仅”提供在该特定类中定义的列,即没有继承的列。如果您需要全部,请使用
self.\uuu映射器\uuuu.columns
。在您的示例中,我可能会使用以下内容:

{'desc': Column('desc', Unicode(length=20), table=<jobstatus>),
 'id': Column('id', Integer(), table=<jobstatus>, primary_key=True, nullable=False)}
class JobStatus(Base):

    ...

    def __iter__(self):
        values = vars(self)
        for attr in self.__mapper__.columns.keys():
            if attr in values:
                yield attr, values[attr]

    def logme(self):
        return dict(self)

为了在我所有的类上获得一个
as__dict
方法,我使用了一个
Mixin
类,它使用了所描述的技术

然后像这样在课堂上使用它

class MyClass(BaseMixin, Base):
    pass
这样,您就可以在
MyClass
的实例上调用以下内容

> myclass = MyClass()
> myclass.as_dict()
希望这有帮助


我把arround玩得更深入了一点,实际上我需要将我的实例呈现为
dict
的形式,并带有到相关对象的链接。所以我在这里添加了这个小魔术,它将爬过与上面相同的类的所有属性,不同的是我将爬过更深的
关系
属性,并自动为这些属性生成
链接

请注意,这仅适用于只有一个主键的关系


我知道这是个老问题,但关于:

class JobStatus(Base):

    ...

    def columns(self):
        return [col for col in dir(self) if isinstance(col, db.Column)]
然后,要获取列名:
jobStatus.columns()

这将返回
['id','desc']

然后您可以循环,并使用列和值执行操作:

for col in jobStatus.colums():
    doStuff(getattr(jobStatus, col))

假设您使用的是SQLAlchemy的声明性映射,那么可以使用
\uuuu映射器\uuuu
属性来获取类映射器。要获取所有映射属性(包括关系),请执行以下操作:

如果需要严格的列名,请使用
obj.\uu映射器\uuuuu.column\u attrs.keys()
。有关其他视图,请参见文档

返回一个dict,其中键是属性名,值是对象的值

/!\还有一个补充属性:“_sa_instance_state”
但是您可以处理它:)

我想动态获取模型的特定实例的数据。我用了这个密码

def to_json(instance):
    # get columns data
    data = {}
    columns = list(instance.__table__.columns)
    for column in columns:
        data[column.name] = instance.__dict__[column.name]
    return data


谢谢,这让我可以在这个基础上创建一个todict方法,然后使用它将一个实例“转储”到一个dict中,然后我可以传递给pylon的jsonify decorator响应。我试图在我的原始问题中添加更多关于代码示例的详细说明,但这会导致stackoverflow在提交时出错。顺便说一句,
class\u mapper
需要从
sqlalchemy.orm
导入,虽然这是一个合理的答案,但在版本0.8之后,建议使用
inspect()
,它返回与
class\u mapper()
完全相同的映射器对象。这对我将SQLAlchemy模型属性名称映射到基础列名有很大帮助。请注意,
\uu table\uuuu.columns
将为您提供SQL字段名,而不是您在ORM定义中使用的属性名(如果两者不同)。我是否可以建议更改
“\u sa”!=k[:4]
而不是k.startswith(“'u sa')
?如果您使用
模型设置值,则无需使用inspect:
inspect(JobStatus).columns.keys()
。\uu dict\uuuu[column]
sqlalchemy不会检测到更改。很好!使用此方法是否也可以获取关系?不需要使用_dataattr,只需..columns.keys()进行操作,尽可能避免使用private _data属性,@Humoyun更正确。AttributeError:u data我还想检索您无法执行的关系isinstance(col,Column)在stringDownvoted上,因为table.columns和mapper.columns在不重新发明轮子的情况下为您提供此数据。请在代码段顶部添加来自sqlalchemy.orm导入类的
,ColumnProperty
,谢谢您的评论!我已经添加了缺少的imports它是sqlalchemy的声明性基础,这里只在设置属性时阅读更多关于它的内容。这是一个简单的答案。
for col in jobStatus.colums():
    doStuff(getattr(jobStatus, col))
obj.__mapper__.attrs.keys()
self.__dict__
def to_json(instance):
    # get columns data
    data = {}
    columns = list(instance.__table__.columns)
    for column in columns:
        data[column.name] = instance.__dict__[column.name]
    return data