在SQLAlchemy中连接表时,是否有便捷方式仅为冲突列创建别名?

3 投票
1 回答
2528 浏览
提问于 2025-04-15 15:24

有时候,在使用 SQLAlchemy 的声明式扩展时,把一个类映射到一个 join 而不是单个表会很有用。当列名发生冲突时,通常是在一对多的情况下,因为所有主键默认都叫 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()

STidfkey 属性,每个名字都映射到连接中第一个表的重命名,所以映射类并没有暴露 t2 的主键。ST2t1_idt2_idt2_fkey 属性。

有没有什么方便的方法,可以只给 join 中每个表的一部分列加别名,这样映射类就能对大多数映射列使用更方便的没有前缀的属性名呢?

1 个回答

5

你可以为每一列单独创建一个别名,方法是使用它的 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))

撰写回答