How to override a column name in sqlalchemy using reflection and descriptive syntax

前端 未结 3 1343
暖寄归人
暖寄归人 2020-12-30 08:40

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

相关标签:
3条回答
  • 2020-12-30 09:08

    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)

    0 讨论(0)
  • 2020-12-30 09:11

    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))
    
    0 讨论(0)
  • 2020-12-30 09:27

    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.

    0 讨论(0)
提交回复
热议问题