简单的SQLAlchemy层次继承模型

2024-09-30 16:20:21 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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以保持用户接收到的消息的完整性。 一个简单的解决方案是有一个用户类和一个潜在的“status”属性,然而,这似乎不是最佳的

有没有具体的方法告诉SQLAlchemy将“InvitedUser”转换为“VerifiedUser”?可能我的模型过于复杂,有一种不同的方法来解决这个问题

谢谢你, 罗伯


Tags: key用户idtrue消息columnintegerclass
1条回答
网友
1楼 · 发布于 2024-09-30 16:20:21

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

  • 创建一个新的VerifiedUser对应于您的InvitedUser
  • 查找所有ChatMessage,其中receiver_id与您的InvitedUser的ID匹配
  • 更新所有此类消息以指向新创建的验证用户

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

注意

您应该仔细考虑是否真的需要两个独立的用户类。请注意,除了polymorphic_identity之外,您提供的定义是相同的,您可以使用status列对其进行同样好的建模,如您在文章的评论中所述。这还有一个好处,那就是概念上要简单得多,而且可以巧妙地避开当前面临的问题

相关问题 更多 >