简单的SQLAlchemy hiearchical继承模型

时间:2016-10-25 21:42:20

标签: python postgresql sqlalchemy relational-database

我正在建模一个简单的分层数据库结构。我的模型设计如下:

class ChatMessage(Base):
    __tablename__ = 'chat_message'
    sender_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
    receiver_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
    text = Column(String(50))


class User(Base):
    __tablename__ = 'user'


    id = Column(Integer, primary_key=True)
    phone_number = Column(PhoneNumberType())
    type = Column(String(50))

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

    sent_messages = relationship(
        'ChatMessage',
        foreign_keys='ChatMessage.sender_id',
        backref='sending_user'
    )

    received_messages = relationship(
        'ChatMessage',
        foreign_keys='ChatMessage.sender_id',
        backref='sending_user'
    )


class InvitedUser(TBHUser):
    __tablename__ = 'invited_user'
    id = Column(Integer, ForeignKey('user.id'), primary_key=True)

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


class VerifiedUser(TBHUser):
    __tablename__ = 'verified_user'
    id = Column(Integer, ForeignKey('user.id'), primary_key=True)

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

我将简要介绍我的应用程序中存在的一些结构性业务规则。单个用户可以与其联系人中的任何人聊天。如果用户向未在应用程序中注册的朋友发送消息,则将发送聊天消息,并且接收用户将收到下载应用程序的邀请。受邀用户存储在“InvitedUser”表中。邀请用户注册后,“InvitedUser”实例将被删除,并将替换为“VerifiedUser”实例。 “InvitedUser”实体的目的是在注册之前保留收到的聊天消息。

从数据库中删除InvitedUser时,我收到以下错误。

AssertionError: Dependency rule tried to blank-out primary key column 'chat_message.receiver_id' on instance '<ChatMessage at 0x1044a9cf8>'

似乎SQLAlchemy不允许删除InvitedUser以保持用户收到的ChatMessages的完整性。 一个简单的解决方案是拥有一个用户类,并且可能具有“状态”属性,但这似乎不是最佳的。

是否有特定的方法告诉SQLAlchemy将“InvitedUser”转移到“VerifiedUser”?可能我的模型过于复杂,并且有一种不同的方法来解决这个问题。

谢谢, 罗布。

1 个答案:

答案 0 :(得分:0)

正如您所提到的,您被阻止删除InvitedUser的原因是因为他们是一个或多个ChatMessage的收件人,如果您删除了您的用户,那么您&# 39;留下一条或多条指向不存在的用户的消息。如果你确信你肯定想要两个不同的用户类,那么你需要:

  • 创建与您的VerifiedUser
  • 对应的新InvitedUser
  • 找到ChatMessagereceiver_id
  • 的ID匹配的所有InvitedUser
  • 更新所有此类消息以指向新创建的VerifiedUser

此时对InvitedUser实体的所有引用都应该消失,您应该能够安全地删除InvitedUser

注意

您应该强烈考虑是否真的需要两个单独的用户类。请注意,除了polymorphic_identity之外,您提供的定义是相同的,您可以使用状态列同样很好地建模,如您帖子中的评论中所述。这样做的好处还在于概念上更加简单,以及整齐地解决您目前面临的问题。