代码之家  ›  专栏  ›  技术社区  ›  pckben

sqlalchemy orm列名约定

  •  0
  • pckben  · 技术社区  · 7 年前

    如何自动映射表单的所有字段 my_column 到相应列 MyColumn 在数据库里?

    class MyTable(Base):
        __tablename__ = 'MyTable'
        # what I have now:
        my_column_1 = Column('MyColumn1', Integer)
        # what I want: how to configure a convention mapping rule for this:
        my_column_1 = Column(Integer)
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Ilja Everilä    7 年前

    在将控件传递给 DeclarativeMeta . 另一种方法是在 before_parent_attach 的事件处理程序 Column ,但与使用特定声明性基的映射类中的列相比,这将全局影响所有列。

    from sqlalchemy.ext.declarative.api import DeclarativeMeta
    from sqlalchemy import Column
    
    class RenamingDeclarativeMeta(DeclarativeMeta):
        def __init__(cls, name, bases, namespace):
            _rename_declared_columns(namespace)
            super().__init__(name, bases, namespace)
    
        def __setattr__(cls, key, value):
            if isinstance(value, Column):
                _undefer_column_name_only(key, value)
            super().__setattr__(key, value)
    
    def to_camelcase(s):
        return ''.join([w.title() for w in s.split('_')])
    
    def _undefer_column_name_only(key, column):
        if column.name is None:
            column.name = to_camelcase(key)
    
    def _rename_declared_columns(namespace):
        for key, attr in namespace.items():
            if isinstance(attr, Column):
                _undefer_column_name_only(key, attr)
    

    ColumnProperty CompositeProperty metaclass declarative_base() :

    In [2]: from sqlalchemy.ext.declarative import declarative_base
    
    In [3]: Base = declarative_base(metaclass=RenamingDeclarativeMeta)
    
    In [4]: from sqlalchemy import Column, Integer
    
    In [5]: class Foo(Base):
       ...:     __tablename__ = 'foo'
       ...:     id = Column(Integer, primary_key=True)
       ...:     bar_baz_1 = Column(Integer, nullable=False)
       ...:     
    
    In [6]: Foo.id
    Out[6]: <sqlalchemy.orm.attributes.InstrumentedAttribute at 0x7ffb7f770e60>
    
    In [7]: Foo.bar_baz_1
    Out[7]: <sqlalchemy.orm.attributes.InstrumentedAttribute at 0x7ffb7dc47200>
    
    In [8]: list(Foo.__table__.columns)
    Out[8]: 
    [Column('Id', Integer(), table=<foo>, key='id', primary_key=True, nullable=False),
     Column('BarBaz1', Integer(), table=<foo>, key='bar_baz_1', nullable=False)]
    

    另一种方法是全局重命名附加到的所有列 Table 对象使用 event API

    from sqlalchemy import event
    
    @event.listens_for(Column, 'before_parent_attach')
    def receive_column_before_table_attach(column, table):
        # As dumb as it gets. Blindly modifies all columns.
        column.name = to_camelcase(column.name)
    

    这个有一个 专业