Как устранить ошибку при работе с двумя базами данных в Flask-SQLAlchemy?

У меня есть приложение на Python, использующее flask-SQLAlchemy версии 1.4. В нём подключены две базы данных, и таблицы второй базы ссылаются на справочник из первой базы. Привожу код моделей ниже: 

```python
class Colors(db.Model):
    __bind_key__ = 'first'
    id = db.Column(db.Integer, primary_key=True)
    color = db.Column(db.String(6))

class Materials(db.Model):
    __bind_key__ = 'first'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    color = db.Column(db.Integer, db.ForeignKey('colors.id'))
    colors = db.relationship(
        'Colors', backref=db.backref('materials', lazy='dynamic')
    )

class Elements(db.Model):
    __bind_key__ = 'second'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    color = db.Column(db.Integer, db.ForeignKey('colors.id'))
    colors = db.relationship(
        'Colors', backref=db.backref('elements', lazy='dynamic')
    )
```

При попытке перейти на flask-SQLAlchemy 2.2 приложение запускается, но после первого запроса возникает ошибка по ForeignKey, указывающая на справочник из второй базы. Это кажется логичным, ведь во второй базе этого справочника нет, однако в старой версии всё работало без проблем. Можете объяснить, в чём причина этой проблемы и как её можно корректно обойти?
  • 18 января 2025 г. 10:33
Ответы на вопрос 1
При переходе на более новую версию Flask-SQLAlchemy могут возникнуть различия в поведении, особенно в отношении работы с несколькими базами данных и отношениями между моделями. Ваша проблема вероятнее всего связана с тем, как Flask-SQLAlchemy обрабатывает связи между моделями, использующими различные базы данных.

В вашем коде вы создали модели `Materials` и `Elements`, которые имеют внешние ключи, ссылающиеся на таблицу `Colors`, расположенную в первой базе данных. Однако при использовании `Flask-SQLAlchemy` версии 2.2, библиотеки могут не поддерживать такие сценарии, так как они требуют, чтобы внешние ключи ссылались на таблицы в той же базе, где находится модель, к которой добавляется связь.

### Способы решения проблемы:

1. **Проверьте конфигурацию привязки**:

   Убедитесь, что правильные `bind_key` используются для подключения к каждой базе. Обратите внимание, что при определении внешнего ключа FLASK-SQLAlchemy ожидает, что ссылка будет в той же базе данных.

2. **Отдельные классы для работы с различными базами**:

   Возможно, вам стоит использовать явное управление сессиями, чтобы гарантировать доступ к данным из обеих баз без прямых внешних связей. Вместо использования отношений вы можете просто извлекать данные из первой базы отдельно и связывать их на уровне приложения, а не на уровне базы данных.

3. **Хранение ID в модели**:

   Вместо того чтобы использовать внешние ключи в модели `Elements`, вы можете просто хранить идентификаторы цветов, например:
   ```python
   class Elements(db.Model):
       __bind_key__ = 'second'
       id = db.Column(db.Integer, primary_key=True)
       name = db.Column(db.String(20))
       color_id = db.Column(db.Integer)
       # можно определить метод для получения цвета по color_id
       def get_color(self):
           return Colors.query.get(self.color_id)
   ```
   Таким образом, вы сможете избежать прямых внешних ключей в модели.

4. **Создание кастомных запросов**:

   Вы можете просто выполнять объединённые запросы с использованием `join` и т.п., когда вам действительно нужно получить данные из двух баз.

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

### Заключение

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