Existe-t-il un moyen pratique d'aliaser uniquement les colonnes en conflit lors de la jonction de tables dans SQLAlchemy?
-
06-07-2019 - |
Question
Il est parfois utile de mapper une classe sur une join
au lieu d'une table unique lorsque vous utilisez SQLAlchemy . Lorsque les noms de colonnes se rencontrent, généralement de manière un-à-plusieurs, car toutes les clés primaires sont nommées id
par défaut, vous pouvez utiliser .alias ()
pour préfixer chaque colonne avec son nom de la table. Cela n’est pas pratique si vous avez déjà écrit du code qui suppose que votre classe mappée a des noms sans préfixe.
Par exemple:
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
possède des propriétés id
, fkey
avec chaque nom mappé sur la première table de la jointure qui utilise le nom substitué. class n'expose pas la clé primaire de t2
. ST2
a les propriétés t1_id
, t2_id
et t2_fkey
.
Existe-t-il un moyen pratique de n'aliaser que certaines des colonnes de chaque table dans join
afin que la classe mappée expose les noms de propriété plus pratiques sans préfixe pour la plupart des colonnes mappées?
La solution
Vous pouvez créer un alias pour chaque colonne séparément avec sa méthode label ()
. Il est donc possible que quelque chose de similaire au suivant (non testé):
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))