SQLAlchemy introspect column type with inheritance
Solution 1
The ORM has allowed you to define classes in an inheritance pattern that corresponds to a JOIN of two tables. This structure is full service, and can also be used to find out basic things like the types of attributes on columns, pretty much directly:
type = Arrete.date.property.columns[0].type
note that this is basically the same thing as the approach of trudging through __bases__
, except you let Python's normal class mechanics do the work.
Solution 2
You can explore the base classes...
def find_type(class_, colname):
if hasattr(class_, '__table__') and colname in class_.__table__.c:
return class_.__table__.c[colname].type
for base in class_.__bases__:
return find_type(base, colname)
raise NameError(colname)
print find_type(Arrete, 'date_arrete')
print find_type(Arrete, 'date')
tonio
Updated on June 03, 2022Comments
-
tonio about 2 years
Considering this code (and using SQLAlchemy 0.7.7):
class Document(Base): __tablename__ = 'document' __table_args__ = { 'schema': 'app' } id = Column(types.Integer, primary_key=True) nom = Column(types.Unicode(256), nullable=False) date = Column(types.Date()) type_document = Column(types.Enum('arrete', 'photographie', name='TYPES_DOCUMENT_ENUM')) __mapper_args__ = {'polymorphic_on': type_document} class Arrete(Document): __tablename__ = 'arrete' __table_args__ = { 'schema': 'app' } __mapper_args__ = {'polymorphic_identity': 'arrete'} id = Column(types.Integer, ForeignKey('app.document.id'), primary_key=True) numero_arrete = Column(types.Integer) date_arrete = Column(types.Date())
I can easily introspect column type for column defined in
Arrete
class with:Arrete.__table__.c['date_arrete'].type
But this doesn’t work if I want to access, through the
Arrete
class, a column defined inDocument
class. (KeyError if I try to accessc['date']
).Is there a way to get column type, regardless if the column is defined in the final class or in one of its parent?
-
tonio almost 12 yearsLooks like it will break some other code of my app for which
Arrete
has to extendDocument
. I don’t want the exact syntax of my example to work (for getting the column type), but why I really want, if possible, is to keep the database unchanged. -
Spencer Rathbun almost 12 years@tonio If Arrete is just extending document, then there should only be one table, called
arrete
, on the db. You can't extend it the way you are wanting, because each__table__
is an object, with a unique entry in themetadata
. Trying to share the__table__
object across classes prevents each class from having different tables. You may need to rethink your db model. Perhaps more details? -
tonio almost 12 yearsI just add it as a @classmethod of my base class, and looks like to work just as expected. Thanks a lot!
-
tonio almost 12 yearsArrete was here as an example, I got more table extending document. And several table with inheritance in my application that I don’t want to change. Maybe I should have better explained my needs, thanks for your help anyway.
-
zzzeek almost 12 yearsthe problem with this answer is that it unnecessarily pokes through
__bases__
, when simply accessingArrete.date
will do that work for you. SQLAlchemy of course can give you the column/datatype given a mapped attribute. -
tonio almost 12 yearsHuh, that's cleaner! Thanks! :)
-
ricekab over 4 years@zzzeek is there a reason the
columns
attribute is a list? Are there situations where the first instance might not be the correct one? -
weaming almost 4 yearssame curiosity as @ricekab