Flask-Migrate multidb external key to different bind не может найти целевую таблицу

Я пытаюсь использовать Flask-Migrate с несколькими базами данных, используя функцию flask-sqlalchemy __binds__. При попытке установить внешний ключ между двумя разными привязками flask db migrate завершается ошибкой sqlalchemy.exc.NoReferencedTableError, т.е. не может найти таблицу для установки внешнего ключа.

Я использую базы данных Postgres с ключами привязки db1 и db2. Обратите внимание, что эта ошибка не возникает, если внешний ключ относится к таблице в той же привязке (базе данных).

Вот пример приложения, демонстрирующего проблему:

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, указывают, что внешний ключ должен быть установлен путем включения имя схемы или ключ привязки:

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'

Мы будем очень благодарны за любые предложения по этому поводу!


person cpkm    schedule 12.06.2019    source источник
comment
Я должен отметить, что для этого запуска есть также файл main.py с from app import app и файл .flaskenv для установки FLASK_APP=main.py.   -  person cpkm    schedule 12.06.2019
comment
Поддерживаются ли внешние ключи в базах данных Postgres? Как это работает?   -  person Miguel    schedule 12.06.2019
comment
Угги. Думаю, ты прав, я даже не подумал об этом. Если вы хотите написать это как ответ, я отмечу это. Спасибо!   -  person cpkm    schedule 14.06.2019


Ответы (2)


Проблема в том, что вы не можете определить внешние ключи для разных баз данных. Если вы можете переместить все эти таблицы в одну базу данных, возможно, поместить их в разные схемы, тогда все будет в порядке.

person Miguel    schedule 14.06.2019

Вы должны установить 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)
person gotounix    schedule 20.06.2019
comment
Я не уверен, что это сработает. Как упоминалось в другом ответе, вы не можете устанавливать внешние ключи для разных баз данных, даже если логика имеет смысл во Flask. Если вы попытаетесь запустить это как сценарий миграции, он не запустится. - person MillerMedia; 07.06.2020
comment
В моем случае у меня есть таблица ‹branch› по умолчанию DATABASE_URI и другая таблица ‹branch› в sqlalchemy_binds. Когда я определяю db.ForeignKey, он всегда выбирает ветку в DATABASE_URI по умолчанию и терпит неудачу, потому что структура ветки отличается. И ваше решение - работа. Спасибо. - person haulpd; 18.05.2021