SQLAlchemy中的继承问题

hit*_*kac 1 python inheritance sqlalchemy

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

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))
Run Code Online (Sandbox Code Playgroud)

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

我错过了SQLAlchemy中的继承点吗?

van*_*van 6

我错过了SQLAlchemy中的继承点吗?

我认为你inheritance一般滥用这个概念,甚至在SA实现细节中也没有.
在一个经典Animal (Cat, Dog (Terier))的等级体系中,你会想象一只猫会上升/下降到一只狗,甚至一种特定类型的狗吗?我不这么认为.另外,我可以想象有些CoolUser也可能Administrator同时出现.你将如何解决这种关系?

因此,对于您的要求,继承不是用于解决此状态变化模型的概念.我建议谷歌User-Role的关系和实施类型.您仍然需要解决存储特定于角色的数据的问题.


正如@aquavitae所提到的:在SA中,你可以黑客攻击并改变它user_type.但请注意,在这种情况下,将发生以下情况:

  • 从数据库加载对象时,其类将反映新类型(GOOD)
  • 当您降级对象(从CoolUser到User)时,与CoolUser对应的行不会被删除(我认为它很糟糕,但可能没问题)
  • 当您升级对象(从User到CoolUser)时,不会创建CoolUser表的新行,并且您的所有值都将为NULL.因此,设置/添加存储在非创建行中的任何属性都会产生错误.当查询特定的子类时,您将不会收回该对象,因为INNER JOIN它用于检索对象.(坏)
  • 总之,不要将猫变成狗

  • +1我应该把所有这些警告放在我的答案中!在这个用例中,使用过滤器简单地查询用户可能更好. (2认同)