which attributes are columns

41 views
Skip to first unread message

Dirk Makowski

unread,
Aug 10, 2011, 7:02:48 AM8/10/11
to sqlal...@googlegroups.com
Hi all,

from a given class I'd like to determine which attributes are columns, not only physical columns present in the underlying table, but also those from a relationship(). The FAQ seems to provide an answer ("What's the best way to figure out which attributes are columns, given a class"), but the proposed solution throws an "sqlalchemy.orm.exc.UnmappedClassError: Class '<pym.models.usrmgr.Principal object at 0x3a69c10>' is not mapped" error in my setup.

I'm using 0.7.2. with declarative classes, e.g.

DbBase = declarative_base()

class Principal(DbBase, PymMixin):
    __tablename__ = "principal"
    __table_args__ = {'schema': 'pym'}
    is_enabled      = Column(Boolean, nullable=False, default=False)
    ...

Does is matter that I try to read the attributes from a query?

qry = sess.query(Principal)
for p in qry:
    print p.display_name
# Determine columns in last looped entity
mapper = class_mapper(p)       #<---- this throws UnmappedClassError
attrs = set()
for prop in mapper.iterate_properties:
   if isinstance(prop, ColumnProperty):
       attrs.add(prop.key)
print "Columns:", attrs

Thanks for your help,
Dirk

Michael Bayer

unread,
Aug 10, 2011, 10:37:13 AM8/10/11
to sqlal...@googlegroups.com
On Aug 10, 2011, at 7:02 AM, Dirk Makowski wrote:

Hi all,

from a given class I'd like to determine which attributes are columns, not only physical columns present in the underlying table, but also those from a relationship(). The FAQ seems to provide an answer ("What's the best way to figure out which attributes are columns, given a class"), but the proposed solution throws an "sqlalchemy.orm.exc.UnmappedClassError: Class '<pym.models.usrmgr.Principal object at 0x3a69c10>' is not mapped" error in my setup.


I'm using 0.7.2. with declarative classes, e.g.

DbBase = declarative_base()

class Principal(DbBase, PymMixin):
    __tablename__ = "principal"
    __table_args__ = {'schema': 'pym'}
    is_enabled      = Column(Boolean, nullable=False, default=False)
    ...

Does is matter that I try to read the attributes from a query?

qry = sess.query(Principal)
for p in qry:
    print p.display_name
# Determine columns in last looped entity
mapper = class_mapper(p)       #<---- this throws UnmappedClassError

"p" here is an instance of a Principal, i.e. "p = Principal(x, y, z..)", not a Principal class.   You'd say either class_mapper(type(p)), or object_mapper(p).

Dirk Makowski

unread,
Aug 10, 2011, 11:58:11 AM8/10/11
to sqlal...@googlegroups.com
Hi Michael,

thank you for the quick answer. object_mapper() solves the UnmappedClassError.

The depicted technique, however, lists just the 'physical' columns. Those defined with relationship() or injected by backref are not included.
I'm not Luke, but I also used the source (thank you for providing it) ;) which pointed me to sqlalchemy.orm.properties.RelationshipProperty. With this I am able to list both kinds of columns:

mapper = object_mapper(p)
attrs = []
for prop in mapper.iterate_properties:
   if isinstance(prop, ColumnProperty):
       attrs.append(prop.key)
   elif isinstance(prop, RelationshipProperty):
       attrs.append(prop.key)
attrs.sort()
print "Columns:", attrs

Regards, Dirk

Michael Bayer

unread,
Aug 10, 2011, 12:39:29 PM8/10/11
to sqlal...@googlegroups.com

OK, little terminology gap here, there's only one kind of "column" in SQLAlchemy and that's "Column", a relationship() is not in any way describable as a "column", so we just call them at the class level "attributes" and at the mapper level "properties". You're looking at properties, each of which is MapperProperty. They all have a key, so easy enough:

print "Attribute keys:", ",".join(prop.key for prop in object_mapper(p).iterate_properties)

ColumnProperty and RelationshipProperty are the two prominent types, others include CompositeProperty and SynonymProperty.


Dirk Makowski

unread,
Aug 10, 2011, 1:14:14 PM8/10/11
to sqlal...@googlegroups.com
Great. Thanks for the explanation.
Reply all
Reply to author
Forward
0 new messages