Python 炼金术中的继承问题

Python 炼金术中的继承问题,python,inheritance,sqlalchemy,Python,Inheritance,Sqlalchemy,我需要一些帮助来理解继承在SQLAlchemy中是如何工作的。我已经为一个具有一些基本功能的用户创建了一个基类。然后是一些特定的用户admin、cooluser、uncoluser。每一个都有独特的功能,所以我决定在SQLAlchemy中使用继承。问题是,我需要能够在任何时候将用户升级为cooluser或UnColuser,并将cooluser降级为user class User(Base): __tablename__ = 'tbl_users' __table_args__

我需要一些帮助来理解继承在SQLAlchemy中是如何工作的。我已经为一个具有一些基本功能的用户创建了一个基类。然后是一些特定的用户admin、cooluser、uncoluser。每一个都有独特的功能,所以我决定在SQLAlchemy中使用继承。问题是,我需要能够在任何时候将用户升级为cooluser或UnColuser,并将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\U cool\U user”中的条目,而不是“tbl\U user”中的条目


我是否错过了SQLAlchemy中的继承点?

您必须使用。基本表中的所有公共属性,并创建2个不同的CoolUser和UnColuser

您必须使用。基本表中的所有公共属性,并创建2个不同的CoolUser和UnColuser

我认为您不应该在同一个表中使用“多态”和“多态标识”。您需要做的是创建一个包含所有用户的基表用户,即使用mapper_args“polymorphic_on”,然后使用“polymorphic_identity”将CoolUser子类化:

class User(Base):
    ...
    __mapper_args__ = {'polymorphic_on': user_type}

class CoolUser(User):
    ...
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'}

然后您可以随意更改用户类型。

我认为您不应该在同一个表中使用“多态”和“多态标识”。您需要做的是创建一个包含所有用户的基表用户,即使用mapper_args“polymorphic_on”,然后使用“polymorphic_identity”将CoolUser子类化:

class User(Base):
    ...
    __mapper_args__ = {'polymorphic_on': user_type}

class CoolUser(User):
    ...
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'}
然后,您可以根据需要更改用户类型

我是否错过了炼金术的传承点

我认为您通常误用了继承概念,甚至在SA实现细节中也没有误用。 在一个经典的动物猫,狗的等级体系中,你会想象猫会被提升/降低到狗的等级,甚至是一个特定的狗的等级吗?我不这么认为。此外,我可以很好地想象,一些酷酷的用户也可以同时成为管理员。您将如何解决这种关系

因此,对于您的需求,继承并不是用来解决这种状态变化模型的概念。我建议谷歌提供用户角色类型的关系和实现。您仍然需要解决存储特定于角色的数据的问题

如前所述:在SA中,您可以随意改变用户类型。但请注意,在这种情况下,将发生以下情况:

从数据库加载对象时,其类将反映新类型 当您将对象从一个CoolUser降级到另一个用户时,与CoolUser相对应的行不会被删除。我认为这是不好的,但可能还可以 将对象从User升级到CoolUser时,不会为CoolUser表创建新行,并且所有值都将为NULL。因此,设置/添加存储在未创建行中的任何属性将抛出一个很好的错误。当查询特定子类时,您将不会收到返回的对象,因为内部联接用于检索对象。令人不快的 总之,不要把猫变成狗 我是否错过了炼金术的传承点

我认为您通常误用了继承概念,甚至在SA实现细节中也没有误用。 在一个经典的动物猫,狗的等级体系中,你会想象猫会被提升/降低到狗的等级,甚至是一个特定的狗的等级吗?我不这么认为。此外,我可以很好地想象,一些酷酷的用户也可以同时成为管理员。您将如何解决这种关系

因此,对于您的需求,继承并不是用来解决这种状态变化模型的概念。我建议谷歌提供用户角色类型的关系和实现。您仍然需要解决存储特定于角色的数据的问题

如前所述:在SA中,您可以随意改变用户类型。但请注意,在这种情况下,将发生以下情况:

从数据库加载对象时,其类将反映新类型 当您将对象从一个CoolUser降级到另一个用户时,与CoolUser相对应的行不会被删除。我认为这是不好的,但可能还可以 将对象从User升级到CoolUser时,不会为CoolUser表创建新行,并且所有值都将为NULL。因此,设置/添加存储在未创建行中的任何属性将抛出一个很好的错误。当查询特定子类时,您将不会收到返回的对象,因为内部联接用于检索对象。令人不快的 总之,不要把猫变成狗
谢谢你的回复,但我还是很困惑。如何将用户类型更改为CoolUser?如果我创建新的CoolUser,它会复制CoolUser表中的用户吗?请检查示例并尝试使用多态性。如果您遇到任何错误,请将该错误写入
我们可以解决它。具有特定模型的数据库已经存在,并且无法更改,因为已经有另一个软件连接到它。我试图做的是使python代码符合该模型。我将不得不重新考虑整件事。。。不过我还是很感谢你的帮助。谢谢你的回复,但我还是很困惑。如何将用户类型更改为CoolUser?如果我创建新的CoolUser,它会复制CoolUser表中的用户吗?请检查示例并尝试使用多态性。如果您遇到任何错误,请写下该错误,以便我们能够解决它。具有特定模型的数据库已经存在,并且无法更改,因为已经有另一个软件连接到该数据库。我试图做的是使python代码符合该模型。我将不得不重新考虑整件事。。。不过,我很感谢您的帮助。除非用户是抽象类,否则用户表上也需要polymorhic_标识。更详细的示例:除非用户是抽象类,否则用户表上也需要polymorhic_标识。更详细的示例:+1我也应该在回答中提出所有这些警告!在这个用例中,使用过滤器查询用户可能更好。谢谢。我想我将不得不重新考虑整个事情。我之所以认为继承是可以理解的,是因为每个用户、CoolUser、uncoluser、Admin都必须登录、注销等等。但我猜我错了……我建议你为面向登录的任务创建一个单独的表,称之为User,并为你拥有的数据模型创建一个层次结构,如Person->CoolPerson,-->UncoolPerson,-->Distributor,然后在Person.User\id上有一个外键你甚至可以使用相同的id值。在这种情况下,管理员可能仍然是用户表上的一个角色或只是一个标志,并且只与用户表相关,而不知道任何关于Person及其后代的信息。+1我也应该在我的回答中提出所有这些警告!在这个用例中,使用过滤器查询用户可能更好。谢谢。我想我将不得不重新考虑整个事情。我之所以认为继承是可以理解的,是因为每个用户、CoolUser、uncoluser、Admin都必须登录、注销等等。但我猜我错了……我建议你为面向登录的任务创建一个单独的表,称之为User,并为你拥有的数据模型创建一个层次结构,如Person->CoolPerson,-->UncoolPerson,-->Distributor,然后在Person.User\id上有一个外键你甚至可以使用相同的id值。在这种情况下,管理员可能仍然是用户表上的一个角色或只是一个标志,并且将只与用户表相关,而不知道任何关于Person及其子代的信息。