Skip to main content
 首页 » 编程设计

python之SQLAlchemy 中的继承问题

2025年05月04日14fff_TT

我需要一些帮助来理解继承在 SQLAlchemy 中的工作原理。我已经为具有一些基本功能的用户创建了一个基类。然后是一些特定的用户(admin、cooluser、uncooluser)。每个都有独特的功能,所以我决定在 SQLAlchemy 中使用继承。问题是我需要能够随时将用户升级为 cooluser 或 uncooluser,并将 cooluser 降级为 user。

class User(Base): 
    __tablename__ = 'tbl_users' 
    __table_args__ = {'mysql_engine': 'InnoDB'} 
 
    user_id = Column(Integer, primary_key = True, unique = True, nullable = False) 
    user_name = Column(String(100), nullable = False, unique = True) 
    password = Column(String(100), nullable = False) 
    user_type = Column('user_type', String(50)) 
    first_name = Column(String(50), nullable = False) 
    last_name = Column(String(50), nullable = False) 
    address = Column(String(50), nullable = False) 
    city = Column(String(20), nullable = False) 
    postal_code = Column(String(10), nullable = False) 
    country_id = Column(Integer, ForeignKey(Contries.country_id)) 
 
    country = relationship('Country', backref = 'users') 
 
    query = Session.query_property() 
 
    __mapper_args__ = {'polymorphic_on': user_type, 'polymorphic_identity': 'User'} 
class CoolUser(User): 
    __tablename__ = 'tbl_cool_user' 
    __table_args__ = {'mysql_engine': 'InnoDB'} 
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'} 
 
    cool_user_id = Column(Integer, ForeignKey(User.user_id, ondelete = 'CASCADE'), primary_key = True) 
    cool_user_balance = Column(Numeric(15, 3)) 

我可以创建一个 CoolUser 而不在“tbl_users”中创建新行,而是使用现有的行吗?可以更改一些设置,以便在删除 CoolUser 时它只删除“tbl_cool_user”中的条目,而不是“tbl_user”吗?

我是否遗漏了 SQLAlchemy 中的继承点?

请您参考如下方法:

Am I missing the point of inheritance in SQLAlchemy?

我认为您在一般情况下滥用了继承概念,甚至在 SA 实现细节中也没有。
在经典的Animal (Cat, Dog (Terier)) 类型的层次结构中,您会想象猫会升级/降级为狗,甚至特定类型的狗?我不这么认为。此外,我完全可以想象某些 CoolUser 也可能同时是 Administrator。你将如何解决这种关系?

因此,根据您的要求,继承不是用来解决这种状态变化模型的概念。我建议在 google 上搜索 User-Role 类型的关系和实现。您仍然需要解决存储角色特定数据的问题。


作为@aquavitae提到:在 SA 中,您可以修改并更改 user_type。但请注意,在这种情况下会发生以下情况:

  • 当您从数据库加载对象时,它的类将反射(reflect)新类型 (GOOD)
  • 当您将对象降级(从 CoolUser 降级为 User)时,对应于 CoolUser 的行将不会被删除(我认为这是 BAD,但可能没问题)
  • 当您升级对象(从 User 到 CoolUser)时,不会为 CoolUser 表创建新行,并且您的所有值都将为 NULL。因此,设置/添加存储在非创建行中的任何属性将抛出一个很好的错误。当查询特定子类时,您将不会收到对象,因为INNER JOIN 用于检索对象。 (不好)
  • 总而言之,不要把猫变成狗