SqlAlchemy - 如何使用模型类而不是物理表名称定义外键列

Nam*_* VU 5 python sqlalchemy

简单来说

我想使用模型类来定义外键列。

我的谷歌搜索没有帮助,所以我在这里问。

在全

通常我们通过物理表名称定义作为外键的列,例如在此处引导

author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
Run Code Online (Sandbox Code Playgroud)

该短语ForeignKey('author.id')有助于将列author_id定义为外键列 - 它指的是表,author其中author是表名。

我想使用模型类名,即

author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
Run Code Online (Sandbox Code Playgroud)

但是这段代码会出错

无法确定关系 XX.YYY 上父/子表之间的联接条件 - 没有链接这些表的外键。确保引用列与foreignkey或foreignkeyconstraint关联,或指定“primaryjoin”表达式。

我们怎样才能做到这一点?

Ser*_*bin 8

简单来说

  • 来自作者以外的模型
    author_id = db.Column(db.Integer, db.ForeignKey(Author.__table__.c.id))

  • 来自作者模型本身,即自我引用 - 只需列出列名称
    author_id = db.Column(db.Integer, db.ForeignKey(id))

  • 不能使用字符串值
    author_id = db.Column(db.Integer, db.ForeignKey('Author.id'))

详细信息

foreignKey接受列作为第一个参数,该参数可以是格式Column或格式的类型schema_name.table_name.column_name或字符串table_name.column_name。您在声明性模型中定义的列将转换为InstumentedAttribute对象。这就是db.ForeignKey(Author.id)导致错误的原因。__table__您可以通过模型的属性访问实际列:

author_id = db.Column(db.Integer, db.ForeignKey(Author.__table__.c['id']))
Run Code Online (Sandbox Code Playgroud)

或者

author_id = db.Column(db.Integer, db.ForeignKey(Author.__table__.c.id))
Run Code Online (Sandbox Code Playgroud)

如果需要定义自引用外键,只需传递列名称即可。虽然模型的声明尚未完成,但它仍然具有Column类型:

id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey(id))
Run Code Online (Sandbox Code Playgroud)

请注意,您不能以这种方式定义外键:

author_id = db.Column(db.Integer, db.ForeignKey('Author.id'))
Run Code Online (Sandbox Code Playgroud)

您需要指定物理表名称,映射类名称不起作用。

  • @NamGVU如果你想使用`ForeignKey(Author.id)`:没有办法在不导入类的情况下使用它。如果你想使用 `ForeignKey('Author.id')`:这是可能的,但 SQLAlchemy 没有这样的功能(你可以尝试子类化 `ForeignKey` 并添加此功能,但这可能相当具有挑战性)。 (2认同)