Hello I\'m trying to port a legacy application to python with sqlalchemy.
The application\'s existing database has about 300 tables and in every table there is a col
You can have your cake and eat it too. Define the columns you want to rename; sqlalchemy will automatically infer any columns you don't mention.
>>> from sqlalchemy import *
>>> from sqlalchemy.ext.declarative import declarative_base
>>>
>>> engine = create_engine("sqlite:///:memory:")
>>>
>>> engine.execute("""
... create table accnt (
... id integer primary key,
... code varchar(20),
... def varchar(50)
... )
... """)
<sqlalchemy.engine.base.ResultProxy object at 0x2122750>
>>>
>>> Base = declarative_base()
>>>
>>> Base.metadata.bind = engine
>>>
>>> class Accnt(Base):
... __tablename__ = 'accnt'
... __table_args__ = {'autoload': True}
... def_ = Column('def', String)
...
>>> Accnt.def_
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x2122e90>
>>> Accnt.code
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x2127090>
>>>
EDIT:
By supplying a __table__
argument, you're telling the declarative extension that you already have a properly configured Table
that you'd like to use. But that's not true; you want to have the def
column referred to by another name in the class. By using __tablename__
and __table_args__
, you defer the construction of the table until after you've told declarative how you want to use that table. There's no elegant work-around if you are dead set on using __table__
. You can provide a property
that aliases the column or you may be able to specify the column as _def = getattr(__table__.c, 'def')
.
Really, you should just use __tablename__
; It's both more convenient and more flexible, and this is a great example of why.
(as an aside, it's most conventional to give alternate identifiers a trailing underscore instead of a leading underscore, use def_
instead of _def
; leading underscores usually signify that the name is 'private' or 'an implementation detail', if the name is meant to be public, but looks like a private name, it may cause more confusion than is necessary)
You could define your Table this way:
mymetadata = MetaData()
Base = declarative_base(metadata=mymetadata)
class Accnt(Base):
__tablename__ = 'accnt'
code = Column(String(20))
def_ = Column(String(50))
This may be too much brute force, but another approach is to use the sqlacodegen
library to auto-generate all the models for your DB, then alter those manually, or tweak sqlacodegen
to build the models using your conventions. It has support for mapping reserved words to other symbols.
See https://pypi.python.org/pypi/sqlacodegen. Nice tool.