Existe uma maneira conveniente de apelido única conflitantes colunas ao juntar tabelas em SQLAlchemy?

StackOverflow https://stackoverflow.com/questions/1627429

  •  06-07-2019
  •  | 
  •  

Pergunta

Às vezes é útil para mapear uma classe contra um join em vez de uma única tabela ao usar SQLAlchemy ' s extensão declarativa. Quando os nomes das colunas colidem, geralmente em um um-para-muitos, porque todas as chaves primárias são nomeados id por padrão, você pode usar .alias() prefixar cada coluna com o nome da tabela. Isso é inconveniente se você já tiver código que assume a sua classe mapeada tem nomes não-prefixado escrita.

Por exemplo:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, Column, Integer, ForeignKeyConstraint

Base = declarative_base()

t1 = Table('t1', 
    Base.metadata, 
    Column('id', Integer, primary_key=True))

t2 = Table('t2', 
    Base.metadata, 
    Column('id', Integer, primary_key=True),
    Column('fkey', Integer),
    ForeignKeyConstraint(['fkey'], [t1.c.id]))

class ST(Base):
    __table__ = t1.join(t2)

class ST2(Base):
    __table__ = t1.join(t2).alias()

ST tem id, propriedades fkey com cada mapeamento de nome para a primeira tabela na junção que usa o nome substituído, então a classe mapeada não expõe chave primária da t2. ST2 tem t1_id, t2_id e t2_fkey propriedades.

Existe uma maneira conveniente de apelido apenas algumas das colunas de cada tabela na join assim a classe mapeada expõe os nomes das propriedades mais convenientes não prefixado para a maioria das colunas mapeadas?

Foi útil?

Solução

Você pode criar alias para cada coluna separadamente com seu método label(). Portanto, é possível algo semelhante ao seguinte (não testado):

from sqlalchemy import select

def alias_dups(join):
    dups = set(col.key for col in join.left.columns) & \
                set(col.key for col in join.right.columns)
    columns = []
    for col in join.columns:
        if col.key in dups:
            col = col.label('%s_%s' % (col.table.name, col.key))
        columns.append(col)
    return select(columns, from_obj=[join]).alias()

class ST2(Base):
    __table__ = alias_dups(t1.join(t2))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top