【问题标题】:Cannot define inter dependent relationships among models using SQLAlchemy无法使用 SQLAlchemy 定义模型之间的相互依赖关系
【发布时间】:2021-07-06 06:04:31
【问题描述】:

在以下代码示例中,ChatMessage 模型具有必填字段 converstaion_id,它定义了与该模型的 ChatConversation 的关系。 ChatConverstation 模型有一个字段 last_message_id 这是对最后一个 ChatMessage 的引用。

我收到来自sqlalchemy 的以下错误消息,但不知道如何解决此问题。请帮忙。

sqlalchemy.exc.InvalidRequestError:初始化映射器映射类 ChatConversation->chat_conversation 时,表达式“ChatMessage”未能找到名称(“ChatMessage”)。如果这是一个类名,请考虑在定义两个依赖类之后将此 relationship() 添加到 类。

我应该如何为这些模型定义架构,以便我可以设置这两种关系(即ChatMessage 模型中的conversation 关系和ChatConversation 模型中的last_message 关系)?

class ChatConversation(db.Model):
  __tablename__ = 'chat_conversation'

  id = db.Column(db.Integer, primary_key=True)
  last_message_id = db.Column(
      db.Integer,
      db.ForeignKey("chat_message.id", ondelete='SET NULL'),
      nullable = True
  )
  last_message = db.relationship('ChatMessage')
class ChatMessage(db.Model):
  __tablename__ = 'chat_message'

  id = db.Column(db.Integer, primary_key=True)
  conversation_id = db.Column(
      db.Integer,
      db.ForeignKey("chat_conversation.id", ondelete='CASCADE'),
      nullable=False
  )
  conversation = db.relationship('ChatConversation')

【问题讨论】:

  • 你不能有循环外键引用。不允许。在某种程度上,这将导致无法安全地删除一些记录。您可以将其设为整数。
  • 如果我从last_message_id 中删除外键约束,我是否能够毫无问题地填充last_message 关系中的数据?
  • 我相信是这样,但您必须将其作为整数,而不是作为 ChatMessage 实例。
  • 感谢您的提醒。我使用hybrid_propery 定义了关系。

标签: python sqlalchemy flask-sqlalchemy


【解决方案1】:

解决方案是使用sqlalchemy中的hybrid_property方法装饰器,并显式定义foreign_keys来解决ForeignKey的歧义。


from sqlalchemy.ext.hybrid import hybrid_property

class ChatConversation(db.Model):
  __tablename__ = 'chat_conversation'

  id = db.Column(db.Integer, primary_key=True)
  last_message_id = db.Column(
      db.Integer,
      db.ForeignKey("chat_message.id", ondelete='SET NULL'),
      nullable = True
  )
  
  @hybrid_property
  def last_message(self):
    return False if not self.last_message_id else ChatMessage.query.get(self.last_message_id)

class ChatMessage(db.Model):
  __tablename__ = 'chat_message'

  id = db.Column(db.Integer, primary_key=True)
  conversation_id = db.Column(
      db.Integer,
      db.ForeignKey("chat_conversation.id", ondelete='CASCADE'),
      nullable=False
  )
  conversation = db.relationship('ChatConversation', foreign_keys = [conversation_id])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    相关资源
    最近更新 更多