В какой-то момент я смог использовать flask db
CLI для генерации моей начальной миграции модели данных. Мое приложение Dockerized, и когда я запускаю его, я вызываю flask db upgrade
в entrypoint.sh
, что выдает:
backend_1 | INFO [alembic.runtime.migration] Context impl MySQLImpl.
backend_1 | INFO [alembic.runtime.migration] Will assume non-transactional DDL.
backend_1 | INFO [alembic.runtime.migration] Running upgrade -> 7f973d2726ef, initial data model
Так что это здорово. Теперь я внес обновления в модель данных и хочу создать миграцию, точно так же, как я мог раньше, с помощью flask db migrate -m 'update games tables'
, который отображает:
INFO [alembic.runtime.migration] Context impl MySQLImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate.compare] Detected removed table 'games'
INFO [alembic.autogenerate.compare] Detected removed table 'game_status'
INFO [alembic.autogenerate.compare] Detected removed table 'positions'
INFO [alembic.autogenerate.compare] Detected removed table 'users'
INFO [alembic.autogenerate.compare] Detected removed table 'game_invites'
Generating /home/backend/database/migrations/versions/55f785302c18_update_games_tables.py ... done
Моя flask db migrate
команда видит таблицы базы данных , но поскольку он не читает никаких данных модели, он думает, что мы хотим удалить их все. Я действительно озадачен этим. Последний пост, который я просмотрел, был этот . Согласно предложениям Мигеля по устранению неполадок в сообщении, у меня есть:
- Подтверждено, что я использую один и тот же
db
во всем контексте приложения (см. Ниже) - Явно импортировал все модели данных перед вызовом
migrate.init_app
- Разрушил и перестроил мою базу данных несколько раз, включая перезапуск каталога миграции с
flask db init
Моя структура каталогов выглядит так, и я Я включу то, что я считаю наиболее важными фрагментами кода ниже:
/backend/
| |__/__init__.py (empty)
| |__/app_factory.py
| |__/backend-entrypoint.sh
| |__/wsgi.py
| |__/config.py
| |__/.flaskenv
|
|__/api (nothing important here)
|
|__/database/
| |__/migrations/... (all the usual stuff here)
| |__/db.py
| |__/models.py
|
|__/tests (nothing important here)
db.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() # <- This is the db that's going to get passed around
models.py
from aenum import Enum
from backend.database.db import db
class Users(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text)
email = db.Column(db.Text)
profile_pic = db.Column(db.Text)
username = db.Column(db.Text)
created_at = db.Column(db.DATETIME)
...
# Here's the part where I'm making changes to the schema.
app_factory.py
from flask import Flask
from flask_migrate import Migrate
from database.db import db
from api import routes as routes
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
db.init_app(app)
migrate = Migrate()
with app.app_context():
app.register_blueprint(routes.routes)
# It's annoying that flask works this way. migrate and models both become part of the application context here
from backend.database.models import (
Users,
Games,
GameStatus,
GameInvites,
Positions
)
migrate.init_app(app, db, directory="/home/backend/database/migrations")
return app
серверная точка входа. sh
#!/usr/bin/env bash
until nc -z -v -w30 $DB_HOST 3306
do
echo "Waiting a second until the database is receiving connections..."
sleep 1
done
flask db upgrade # construct the data model
python wsgi.py # start the web application
wsgi.py
from backend.app_factory import create_app
from config import Config
app = create_app()
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=Config.DEBUG_MODE, ssl_context=("cert.pem", "key.pem"))
config.py
...
class Config:
...
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}?charset=utf8"
...
.flaskenv
FLASK_APP=/home/backend/wsgi.py
Это сработало в какой-то момент, но ничего из того, что я пробовал сегодня, включая разрушение всей базы данных, восстановление контейнера и начало с нуля с помощью flask db init
, не дало мне никаких где. Проблема не в том, что изменения не обнаруживаются, а в том, что flask db
даже не подключается к нужной базе данных, хотя я установил Migrate
в контексте приложения flask. У меня есть функциональные тесты, которые я запускаю для сервера API, на котором работает приложение flask, и у него нет проблем с взаимодействием с заполненной базой данных. Проблема кажется довольно ограниченной для flask db
CLI. Я попытался вернуться к более ранним версиям, чтобы узнать, смогу ли я определить, повредило ли что-то изменение в моей файловой структуре, но эта проблема сохраняется при нескольких коммитах.