SQLAlchemy:多个表的外键

3kt*_*3kt 8 python postgresql sqlalchemy

让我们考虑 3 个表:

  • 图书
  • 美国作家
  • 英国作家

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

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

我想要一列来处理链接。


到目前为止,我的方法是创建一个抽象类Author,从它AmericanAuthorBritishAuthor继承,并具有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"))
Run Code Online (Sandbox Code Playgroud)

它失败并出现错误:

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'
Run Code Online (Sandbox Code Playgroud)

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

lor*_*ile 8

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

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

通过这种方式,您可以使用以下方法获取作者: mybook.author


小智 8

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

您的 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
Run Code Online (Sandbox Code Playgroud)