Есть ли удобный способ псевдонима только конфликтующих столбцов при объединении таблиц в SQLAlchemy?
-
06-07-2019 - |
Вопрос
Иногда полезно сопоставить класс с join
вместо одной таблицы при использовании Декларативное расширение SQLAlchemy . Когда имена столбцов сталкиваются, как правило, в формате «один ко многим», поскольку все первичные ключи по умолчанию называются id
, вы можете использовать .alias ()
, чтобы поставить перед каждым столбцом имя таблицы Это неудобно, если вы уже написали код, предполагающий, что у вашего сопоставленного класса есть имена без префиксов.
Например:
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
имеет свойства id
, fkey
, каждое сопоставление имени с первой таблицей в объединении, которое использует переопределенное имя, поэтому сопоставляемое имя класс не предоставляет первичный ключ t2
. ST2
имеет свойства t1_id
, t2_id
и t2_fkey
.
Есть ли удобный способ для псевдонима только некоторых столбцов из каждой таблицы в join
, чтобы отображаемый класс предоставлял более удобные имена без префиксов для большинства отображаемых столбцов?
Решение
Вы можете создать псевдоним для каждого столбца отдельно с помощью метода label ()
. Так что возможно что-то похожее на следующее (не проверено):
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))