从SQLAlchemy表模型获取表列

38 投票
5 回答
46966 浏览
提问于 2025-04-18 14:46

我有一个表格,我想获取所有的列名,但在网上找了半天也没找到有效的方法。我的表格长这样:

class myTable(Base):
    __tablename__ = 'myTable'

    col1 = Column(Integer, primary_key=True)
    col2 = Column(Unicode(10))
    col3 = Column(Integer)

    col4 = Column(Numeric(10, 6))
    col5 = Column(Numeric(6,3))
    col6 = Column(Numeric(6,3))

    child = relationship('tChild',
                          backref=backref('children'))

我想通过一个循环来打印出所有的列名,比如:

"col1", "col2", "col3".... etc

用普通的SQL来做这件事很简单,但我就是搞不定怎么用sqlAlchemy的表模型来实现。

5 个回答

-1

理解列是类的成员,所以它们会被存储在类的 __dict__ 属性中。

因此,使用 myTable.__dict__.keys() 可以得到一个包含列名的列表,还有其他类的成员。

这对于想了解你正在使用的任何类的成员或方法是很有帮助的。

1

因为这个问题在搜索引擎上很热门,我想补充一下,如果你在使用核心功能的话,可以通过下面的代码来获取列信息:

your_table.c

如果你在使用像OP那样的ORM(对象关系映射),那么被接受的答案是有效的。

3

你可以从 __table__.columns 获取所有的列:

这确实是对的,但你应该避免直接访问对象的“保护”和“私有”成员。如果你尝试这样做,你的代码检查工具会提醒你。

正确的方式是通过 SQLAlchemy 的 运行时检查 API 来访问表的列。从文档中可以看到:

inspect() 的返回值保证遵循文档中描述的 API,这样可以让基于 SQLAlchemy 配置构建的第三方工具向前兼容。

你可以这样使用它:

from sqlalchemy import inspect

# ###########################################
# Inspect a Mapped Ojbect
#  https://docs.sqlalchemy.org/en/20/orm/mapping_styles.html#orm-mapper-inspection-mapper
# ###########################################
mapped_object = inspect(myTable)
mapped_object.columns.items()
[('col1',
  Column('col1', Integer(), table=<myTable>, primary_key=True, nullable=False)),
 ('col2', Column('col2', Unicode(length=10), table=<myTable>)),
 ('col3', Column('col3', Integer(), table=<myTable>)),
 ('col4', Column('col4', Numeric(precision=10, scale=6), table=<myTable>)),
 ('col5', Column('col5', Numeric(precision=6, scale=3), table=<myTable>)),
 ('col6', Column('col6', Numeric(precision=6, scale=3), table=<myTable>))]

[column.key for column in mapped_object.columns]
['col1', 'col2', 'col3', 'col4', 'col5', 'col6']

# ###########################################
# Inspect a Mapped Instance
#  https://docs.sqlalchemy.org/en/20/orm/mapping_styles.html#orm-mapper-inspection-instancestate
# ###########################################
my_table = myTable(...)
mapped_instance = inspect(my_table)

# Notice: This collection include 'child'.  The columns from the mapped object did not.
mapped_instance.attrs.items()
[('child', <sqlalchemy.orm.state.AttributeState at 0xffff9c748130>),
 ('col1', <sqlalchemy.orm.state.AttributeState at 0xffff9c7481f0>),
 ('col2', <sqlalchemy.orm.state.AttributeState at 0xffff9c748190>),
 ('col3', <sqlalchemy.orm.state.AttributeState at 0xffff9c7482b0>),
 ('col4', <sqlalchemy.orm.state.AttributeState at 0xffff9c748100>),
 ('col5', <sqlalchemy.orm.state.AttributeState at 0xffff9c748160>),
 ('col6', <sqlalchemy.orm.state.AttributeState at 0xffff9c748370>)]

# Notice: You can get the same collection as the mapped object returned by going through the mapper.
mapped_instance.mapper.columns.items()
[('col1',
  Column('col1', Integer(), table=<myTable>, primary_key=True, nullable=False)),
 ('col2', Column('col2', Unicode(length=10), table=<myTable>)),
 ('col3', Column('col3', Integer(), table=<myTable>)),
 ('col4', Column('col4', Numeric(precision=10, scale=6), table=<myTable>)),
 ('col5', Column('col5', Numeric(precision=6, scale=3), table=<myTable>)),
 ('col6', Column('col6', Numeric(precision=6, scale=3), table=<myTable>))]


4

下面是一个基于@ChaimG回答的通用 as_dict 实现,适用于sqlalchemy表。同时还提供了一个使用它实现的 __repr__ 示例。

from orm.base import Base


class MyTable(Base):
    __tablename__ = 'table_name'

    # Columns go here.....

    def as_dict(self):
        """
        Helper function that allows traversing the table's instance columns as key values

        :return: (key, value) iterator
        """
        for key in self.__table__.columns.keys():
            value = self.__getattribute__(key)
            yield key, value

    def __repr__(self):
        """
        General __repr__ implementation for an sqlalchemy table
        """
        values = []
        for key, value in self.as_dict():
            key_value_str = f"{key}={value}"
            values.append(key_value_str)

        values_str = ", ".join(values)
        cls_name = self.__class__.__name__
        return f"<{cls_name}({values_str})>"
53

你可以从 __table__.columns 中获取所有的列:

myTable.__table__.columns

或者

myTable.__table__.c

这些列的格式是 myTable.col1(包含了表的名字)。如果你只想要列的名字,可以获取每一列的 .key

[column.key for column in myTable.__table__.columns]

撰写回答