【问题标题】:SQLAlchemy: foreign key to multiple tablesSQLAlchemy:多个表的外键
【发布时间】:2019-11-24 05:13:26
【问题描述】:

让我们考虑 3 个表:

  • 书籍
  • 美国作家
  • 英国作家

每本书都有其作者的外键,可以在美国表中,也可以在英国表中。

如何在 SQLAlchemy 中实现这样的外键条件?

我想要一个单独的列来处理链接。


到目前为止,我的方法是创建一个抽象类AuthorAmericanAuthorBritishAuthor 都从该类继承,并让Book 的外键指向父级。

class Author(Model):
    __abstract__ = True
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)

class AmericanAuthor(Author):
    __tablename__ = 'american_author'
    # some other stuff

class BritishAuthor(Author):
    __tablename__ = 'british_author'
    # some other stuff

class Book(Model):
    __tablename__ = 'book'
    title = db.Column(db.String)
    author_id = db.Column(db.Integer, db.ForeignKey("author.id"))

它失败并出现错误:

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'books.author_id' could not find table 'author' with which to generate a foreign key to target column 'id'

这完全有道理,考虑到author 是抽象的......

【问题讨论】:

  • 这篇文章可能会对您有所帮助。干杯! stackoverflow.com/questions/7884359/…
  • @danielschnoll 在我看来,这篇文章使用了多对多关系,我想在这里避免。此外,技术堆栈有些不同,这可能会导致不同的答案(尽管我不知道 Django 中的底层 ORM 提供程序是什么)。无论如何,感谢您的有趣阅读:)

标签: python postgresql sqlalchemy


【解决方案1】:

我认为您无法使用同一列与两个不同的表建立关系。

尝试创建两个不同的列(“american_author_id”和“british_author_id”),然后创建一个@property“author”,返回不为 NULL 的作者。

这样你就可以得到作者使用:mybook.author

【讨论】:

    【解决方案2】:

    虽然@property 装饰器可以在应用程序中工作,但使用sqlalchemy.ext.hybrid 包中的@hybrid_property 可能会更好。通过这种方式,您将能够像任何普通属性一样过滤该属性。

    您的 Book 类将如下所示:

    class Book(Model):
        __tablename__ = 'book'
        title = db.Column(db.String)
        american_author_id = db.Column(db.Integer, db.ForeignKey("american_author.id"), nullable=True)
        british_author_id = db.Column(db.Integer, db.ForeignKey("british_author.id"), nullable=True)
    
        @hybrid_property
        def author_id(self):
            return self.american_author_id or self.british_author_id
    

    【讨论】:

    • 我不知道,很有趣!谢谢:)
    猜你喜欢
    • 2021-06-15
    • 2020-08-16
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2021-07-02
    • 2020-12-30
    相关资源
    最近更新 更多