feat: Integrate Flask-Migrate as a Flask extension and update migration commands to use flask db.
This commit is contained in:
parent
8c4b5462b1
commit
42a4ad3b82
5 changed files with 60 additions and 53 deletions
|
|
@ -4,7 +4,7 @@ load_dotenv()
|
|||
|
||||
from flask import Flask
|
||||
from app.config import Config
|
||||
from app.extensions import db, login_manager
|
||||
from app.extensions import db, login_manager, migrate
|
||||
from app.utils import generate_google_maps_url
|
||||
|
||||
def create_app(config_class=Config):
|
||||
|
|
@ -13,6 +13,7 @@ def create_app(config_class=Config):
|
|||
|
||||
# Initialize Extensions
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = 'auth.login'
|
||||
login_manager.login_message = "Por favor, faça login para acessar esta página."
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_login import LoginManager
|
||||
from flask_migrate import Migrate
|
||||
|
||||
db = SQLAlchemy()
|
||||
login_manager = LoginManager()
|
||||
migrate = Migrate()
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
import logging
|
||||
from logging.config import fileConfig
|
||||
|
||||
from flask import current_app
|
||||
|
||||
from alembic import context
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Adicione o diretório raiz do projeto ao sys.path para importar app
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
from app import db, User, Party, Guest # Importe db e seus modelos
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
|
|
@ -19,26 +14,41 @@ config = context.config
|
|||
fileConfig(config.config_file_name)
|
||||
logger = logging.getLogger('alembic.env')
|
||||
|
||||
|
||||
def get_engine():
|
||||
try:
|
||||
# this works with Flask-SQLAlchemy<3 and Alchemical
|
||||
return current_app.extensions['migrate'].db.get_engine()
|
||||
except (TypeError, AttributeError):
|
||||
# this works with Flask-SQLAlchemy>=3
|
||||
return current_app.extensions['migrate'].db.engine
|
||||
|
||||
|
||||
def get_engine_url():
|
||||
try:
|
||||
return get_engine().url.render_as_string(hide_password=False).replace(
|
||||
'%', '%%')
|
||||
except AttributeError:
|
||||
return str(get_engine().url).replace('%', '%%')
|
||||
|
||||
|
||||
# add your model's MetaData object here
|
||||
# for 'autogenerate' support
|
||||
target_metadata = db.metadata
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
config.set_main_option('sqlalchemy.url', get_engine_url())
|
||||
target_db = current_app.extensions['migrate'].db
|
||||
|
||||
# other values from the config, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
# my_important_option = config.get_main_option("my_important_option")
|
||||
# ... etc.
|
||||
|
||||
# Configura a URL do banco de dados diretamente da variável de ambiente
|
||||
DATABASE_URL = os.environ.get('DATABASE_URL')
|
||||
if not DATABASE_URL:
|
||||
raise ValueError("A variável de ambiente 'DATABASE_URL' não foi definida. Ela é essencial para a conexão com o PostgreSQL.")
|
||||
|
||||
# Algumas plataformas (como Heroku e versões mais antigas do Render) usam "postgres://"
|
||||
# enquanto o SQLAlchemy espera "postgresql://". Esta linha garante a compatibilidade.
|
||||
if DATABASE_URL.startswith("postgres://"):
|
||||
DATABASE_URL = DATABASE_URL.replace("postgres://", "postgresql://", 1)
|
||||
|
||||
config.set_main_option('sqlalchemy.url', DATABASE_URL)
|
||||
def get_metadata():
|
||||
if hasattr(target_db, 'metadatas'):
|
||||
return target_db.metadatas[None]
|
||||
return target_db.metadata
|
||||
|
||||
|
||||
def run_migrations_offline():
|
||||
|
|
@ -55,10 +65,7 @@ def run_migrations_offline():
|
|||
"""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url,
|
||||
target_metadata=target_metadata,
|
||||
literal_binds=True,
|
||||
dialect_opts={"paramstyle": "named"},
|
||||
url=url, target_metadata=get_metadata(), literal_binds=True
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
|
|
@ -72,38 +79,35 @@ def run_migrations_online():
|
|||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
from sqlalchemy import engine_from_config
|
||||
from sqlalchemy import pool
|
||||
|
||||
connectable = engine_from_config(
|
||||
config.get_section(config.config_ini_section),
|
||||
prefix="sqlalchemy.",
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
# this callback is used to prevent an auto-migration from being generated
|
||||
# when there are no changes to the schema
|
||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||
def process_revision_directives(context, revision, directives):
|
||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||
script = directives[0]
|
||||
if script.upgrade_ops.is_empty():
|
||||
directives[:] = []
|
||||
logger.info('No changes in schema detected.')
|
||||
|
||||
conf_args = current_app.extensions['migrate'].configure_args
|
||||
if conf_args.get("process_revision_directives") is None:
|
||||
conf_args["process_revision_directives"] = process_revision_directives
|
||||
|
||||
connectable = get_engine()
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
compare_type=True, # Importante para detectar mudanças de tipo
|
||||
# this callback is used to prevent an auto-migration from being generated
|
||||
# when there are no changes to the schema
|
||||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
|
||||
process_revision_directives=process_revision_directives,
|
||||
target_metadata=get_metadata(),
|
||||
**conf_args
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
def process_revision_directives(context, revision, directives):
|
||||
if getattr(config.cmd_opts, 'autogenerate', False):
|
||||
script = directives[0]
|
||||
if script.upgrade_ops.is_empty():
|
||||
directives[:] = []
|
||||
logger.info('No changes in schema detected.')
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
run_migrations_online()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""Reset e criação inicial das tabelas
|
||||
|
||||
Revision ID: de7b1978faca
|
||||
Revision ID: 091bc7ece679
|
||||
Revises:
|
||||
Create Date: 2025-07-07 03:10:24.781322
|
||||
Create Date: 2026-01-31 01:12:37.522590
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
|
|
@ -10,7 +10,7 @@ import sqlalchemy as sa
|
|||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'de7b1978faca'
|
||||
revision = '091bc7ece679'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
|
@ -75,16 +75,16 @@ check_success "Limpeza do Banco de Dados"
|
|||
# --- PASSO 2: CRIAR MIGRAÇÕES ---
|
||||
echo -e "\n${GREEN}--> PASSO 2: Criando um novo histórico de migrações...${NC}"
|
||||
|
||||
echo "Executando: python manage.py db init"
|
||||
python manage.py db init
|
||||
echo "Executando: flask db init"
|
||||
flask db init
|
||||
check_success "'db init'"
|
||||
|
||||
echo "Executando: python manage.py db migrate"
|
||||
python manage.py db migrate -m "Reset e criação inicial das tabelas"
|
||||
echo "Executando: flask db migrate"
|
||||
flask db migrate -m "Reset e criação inicial das tabelas"
|
||||
check_success "'db migrate'"
|
||||
|
||||
echo "Executando: python manage.py db upgrade"
|
||||
python manage.py db upgrade
|
||||
echo "Executando: flask db upgrade"
|
||||
flask db upgrade
|
||||
check_success "'db upgrade'"
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue