根据父类和多态标识获取多态子类

1 投票
3 回答
1069 浏览
提问于 2025-04-18 06:45

如果我有使用 SQLAlchemy 的多态子类,有没有办法根据一个父类和多态标识来找到一个子类呢?

比如:

class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    type = Column(String(50))

    __mapper_args__ = {
        'polymorphic_identity':'employee',
        'polymorphic_on':type
    }

class Engineer(Employee):
    __tablename__ = 'engineer'
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    engineer_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'engineer',
    }

class Manager(Employee):
    __tablename__ = 'manager'
    id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
    manager_name = Column(String(30))

    __mapper_args__ = {
        'polymorphic_identity':'manager',
    }

有没有办法像这样获取 Engineer 类:

get_subclass(Employee, 'engineer')

我可以自己编写一个已知子类的字典,但我希望能找到 SQLAlchemy 提供的现成方法来做到这一点。

3 个回答

1

这是我怎么做到的。

from sqlalchemy.orm import class_mapper
mapping = {}
for mapper in class_mapper(Employee).polymorphic_iterator():
    mapping[mapper.polymorphic_identity] = mapper

...

# in a from-json function, where app_data["type"] is the discriminator
node_class = mapping[app_data["type"]].class_
1

我在我的项目里有一个函数,可能对你有帮助。

def make_class_by_discriminator_dict(module_name, root_cls=object):
    result = {}
    clss = inspect.getmembers(sys.modules[module_name], inspect.isclass)
    for _, cls in clss:
        if cls.__module__ == module_name and issubclass(cls, root_cls):
            try:
                discriminator = cls.__mapper_args__['polymorphic_identity']
                result[discriminator] = cls
            except (AttributeError, KeyError):
                pass
    return result

现在你需要的是

make_class_by_discriminator_dict(module_name, Employee)['engineer']
4

基础类的映射器有一个叫做 polymorphic_map 的属性,这个属性可以把多态的身份映射到它们各自的映射器上,从那里你就可以获取到对应的类。所以你只需要:

Employee.__mapper__.polymorphic_map['engineer'].class_

撰写回答