【问题标题】:Flask-Migrate multidb foreign key to different bind can not find target tableFlask-Migrate multidb外键到不同的绑定找不到目标表
【发布时间】:2019-10-27 01:45:11
【问题描述】:

我正在尝试使用 flask-sqlalchemy __binds__ 功能将 Flask-Migrate 与多个数据库一起使用。当尝试在两个不同的绑定之间建立外键时,flask db migrate 失败并出现错误sqlalchemy.exc.NoReferencedTableError,即找不到建立外键的表。

我正在使用带有绑定键 db1db2 的 Postgres 数据库。请注意,如果外键指向同一绑定(数据库)上的表,则不会发生此错误。

这是一个演示问题的示例应用程序:

app/models.py

from app import db

class People(db.Model):
    __bind_key__ = 'db1'

    id = db.Column(db.Integer, primary_key=True)


class Cats(db.Model):
    __bind_key__ = 'db2'

    id = db.Column(db.Integer, primary_key=True)
    people_id = db.Column(db.Integer, db.ForeignKey('people.id'))
    dogs_id = db.Column(db.Integer, db.ForeignKey('dogs.id'))


class Dogs(db.Model):
    __bind_key__ = 'db2'

    id = db.Column(db.Integer, primary_key=True)

app/init.py

from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app,db)

from app import models

config.py 文件用于从环境变量设置 sqlalchemy 绑定:

config.py

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config(object):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
    SQLALCHEMY_BINDS = {
        'db1': os.environ.get('DATABASE_1_URL'),
        'db2': os.environ.get('DATABASE_2_URL')}

在这个例子中,Cats 表中的外键到Dogs 表的建立没有错误:

dogs_id = db.Column(db.Integer, db.ForeignKey('dogs.id'))

但是对People 表做同样的事情,

people_id = db.Column(db.Integer, db.ForeignKey('people.id')) 运行flask db migrate时导致报错:

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'cats.people_id' could not find table 'people' with which to generate a foreign key to target column 'id'

线程,如this one 表示应该通过包含架构名称或绑定键来建立外键:

people_id = db.Column(db.Integer, db.ForeignKey('db1.people.id'))

但是,这会导致同样的错误:

sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'cats.people_id' could not find table 'db1.people' with which to generate a foreign key to target column 'id'

对此的任何建议将不胜感激!

【问题讨论】:

  • 我应该注意,为了让这个运行,还有一个带有from app import appmain.py 文件和一个.flaskenv 文件来设置FLASK_APP=main.py
  • Postgres 是否支持跨数据库的外键?它是如何工作的?
  • Ugg 我认为你是对的,我什至没有考虑过。如果您想将其写为答案,我会标记它。谢谢!

标签: python postgresql flask sqlalchemy flask-migrate


【解决方案1】:

问题是您不能跨数据库定义外键。如果您可以将所有这些表移动到一个数据库中,也许将它们放在不同的模式中,那么您会没事的。

【讨论】:

    【解决方案2】:

    你应该设置schema并用它设置外键。

    class People(db.Model):
        __bind_key__ = 'db1'
        __table_args__ = {'schema': 'db1'}
    
        id = db.Column(db.Integer, primary_key=True)
    
    
    class Cats(db.Model):
        __bind_key__ = 'db2'
        __table_args__ = {'schema': 'db2'}
    
        id = db.Column(db.Integer, primary_key=True)
        people_id = db.Column(db.Integer, db.ForeignKey('db1.people.id'))
        dogs_id = db.Column(db.Integer, db.ForeignKey('db2.dogs.id'))
    
    
    class Dogs(db.Model):
        __bind_key__ = 'db2'
        __table_args__ = {'schema': 'db2'}
    
        id = db.Column(db.Integer, primary_key=True)
    

    【讨论】:

    • 我不确定这是否可行。正如另一个答案中提到的,即使逻辑在 Flask 中有意义,您也不能在不同的数据库中设置外键。一旦您尝试将其作为迁移脚本运行,它将不会运行。
    • 在我的例子中,我在默认 DATABASE_URI 中有一个 表,在 sqlalchemy_binds 中有一个 表。当我定义 db.ForeignKey 时,它总是在默认 DATABASE_URI 中选择分支并失败,因为分支结构不同。你的解决方案是工作。谢谢。
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 2021-04-24
    • 2018-05-19
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多