如何从 SQLAlchemy 结果(声明性语法)获取列名

我在一个金字塔项目中工作,我在 SQLAlchemy 中使用了声明性语法

"""models.py"""
class Projects(Base):
__tablename__ = 'projects'
__table_args__ = {'autoload': True}

我通过使用

""""views.py"""
session = DBSession()
row_data = session.query(Projects).filter_by(id=1).one()

如何从这个结果中获得列名。

PS: 我无法使用 这个方法,因为我使用的是声明性语法。

127964 次浏览

ORM 和非 ORM 之间的区别在于它们不是声明性的,而只是 ORM 的助手。

Query 有一个为此添加的方法 column_descriptions():

Http://www.sqlalchemy.org/docs/orm/query.html#sqlalchemy.orm.query

这个例子看起来好像有一个打印错误,说 q.columns,但它应该是 q.column_descriptions(编辑: 刚刚修复)。

随便玩玩,这个语法会给你所有的列(所以为了解决你的问题,设置查询只查看一个表/对象) :

conn.execute(query)._metadata.keys

你可以做一些类似于 Foo Stack 的回答,而不用求助于私有字段:

conn.execute(query).keys()
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (Column, Index, Date, DateTime, Numeric, BigInteger, String, ForeignKey, Boolean)


Base = declarative_base()


class Project(Base):
"""sqlalchemy ORM for my table."""
__tablename__ = "table1"
id = Column("id", BigIntegerID, primary_key=True, autoincrement=True)
date = Column("date", Date, nullable=False)
value = Column("value", Numeric(20, 8))
...
...

然后返回列名[‘ id’,‘ date’,‘ value’,... ] :

Project.__table__.columns.keys()

或者这个

Project.metadata.tables['table1'].columns.keys()

这个链接显示了如何获取所有可能需要的关于表、列等的元数据。

SQLAlchemy 元数据

上面的许多答案都是基于这个页面上的信息。 假设我们声明了一个表。

employees = Table('employees', metadata,
Column('employee_id', Integer, primary_key=True),
Column('employee_name', String(60), nullable=False),
Column('employee_dept', Integer, ForeignKey("departments.department_id"))
)

下面是一些获取有关表的元数据的示例。

# access the column "EMPLOYEE_ID":
employees.columns.employee_id


# or just
employees.c.employee_id


# via string
employees.c['employee_id']


# iterate through all columns
for c in employees.c:
print(c)


# get the table's primary key columns
for primary_key in employees.primary_key:
print(primary_key)


# get the table's foreign key objects:
for fkey in employees.foreign_keys:
print(fkey)


# access the table's MetaData:
employees.metadata


# access the table's bound Engine or Connection, if its MetaData is bound:
employees.bind


# access a column's name, type, nullable, primary key, foreign key
employees.c.employee_id.name
employees.c.employee_id.type
employees.c.employee_id.nullable
employees.c.employee_id.primary_key
employees.c.employee_dept.foreign_keys


# get the "key" of a column, which defaults to its name, but can
# be any user-defined string:
employees.c.employee_name.key


# access a column's table:
employees.c.employee_id.table is employees


# get the table related by a foreign key
list(employees.c.employee_dept.foreign_keys)[0].column.table

只是

>>> q[0].keys()

之后

row_data = session.query(Projects).filter_by(id=1).one()

例如:

>>> q = session.query(users_user.phone,users_user.first_name).filter(users_user.phone=='79267548577').limit(1).all()
>>> columns_names = q[0].keys

结果:

>>> q[0].keys()
['phone', 'first_name']
>>>

想要扩展@zzzeek 的回答。实际上 Query 具有 column_descriptions属性,但是它并不适用于所有的方法。

考虑以下两个查询:

1. query = session.query(Projects).filter_by(<filter_condition>)
2. query = session.query(Projects).all() <-- This query does not have column_descriptions.

因此,如果你遇到这种情况,你需要使用 column_descriptions属性,但使用 ...query(...).all(),那么你可以改变它为 ...query(...).filter_by(),即 filter_by()没有任何过滤条件。

简短的回答是,我最终得到了以下解决方案:

column_names = query.statement.columns.keys()

为什么?

我有一个类似的用例,需要知道查询返回的显式列(即,查询不一定包含表类的所有列)。由于表的规模也很大(数百万条目) ,ProLibertas的回答在性能方面并不令人满意。下面是我的表中94列的性能比较:

# First create a query with 100.000 entries
query = (
session.query(myTable)
.limit(100000)
)


# Then get the column names ..


column_names = session.execute(query).keys()
# ---> ~ 5.730 seconds


column_names = query.statement.columns.keys()
# ---> ~ 0.003 seconds