我需要一些帮助来理解继承在 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用于检索对象。 (不好) - 总而言之,不要把猫变成狗
