Alembic создаёт пустые миграции
Проблема: после alembic revision --autogenerate создаётся пустая миграция (модели не подгрузились). Скорее всего, alembic не видит модели. Поэтому я решил все в один файл засунуть, т.е. в wallet_model, но это тоже не помогло.
Файл wallet_model:
from sqlalchemy import Column, Numeric, DateTime, text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from sqlalchemy.orm import declarative_base
# База для моделей
Base = declarative_base()
class Wallet(Base):
__tablename__ = "wallets"
id = Column(
UUID(as_uuid=True),
primary_key=True,
server_default=text("gen_random_uuid()")
)
balance = Column(
Numeric(15, 2),
nullable=False,
default=0.00,
server_default="0.00"
)
created_at = Column(
DateTime(timezone=True),
server_default=func.now()
)
updated_at = Column(
DateTime(timezone=True),
onupdate=func.now()
)
Файл env.py:
from logging.config import fileConfig
from dotenv import load_dotenv
from os import getenv
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
from models.wallet_model import Base
from models.wallet_model import Wallet
config = context.config
load_dotenv()
POSTGRES_USER = getenv('POSTGRES_USER')
POSTGRES_PASS = getenv('POSTGRES_PASSWORD')
POSTGRES_HOST = getenv('POSTGRES_HOST')
POSTGRES_PORT = getenv('POSTGRES_PORT')
POSTGRES_DB = getenv('POSTGRES_DB')
DB_URL = (
f"postgresql+asyncpg://{POSTGRES_USER}:{POSTGRES_PASS}"
f"@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}"
)
if config.config_file_name is not None:
fileConfig(config.config_file_name)
inclued_schemas = True
config.set_main_option("sqlalchemy.url", DB_URL + "?async_fallback=True")
target_metadata = Base.metadata
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
alembic.ini:
[alembic]
script_location = src/alembic
prepend_sys_path = . src
version_path_separator = os
sqlalchemy.url = driver://user:pass@localhost/dbname
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARNING
handlers = console
qualname =
[logger_sqlalchemy]
level = WARNING
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
Структура:
│ .env
│ .env example
│ .gitignore
│ alembic.ini
│ docker-compose.yml
│ Dockerfile
│ README.md
│ requirements.txt
│
├───.pytest_cache
│ │ .gitignore
│ │ CACHEDIR.TAG
│ │ README.md
│ │
│ └───v
│ └───cache
│ lastfailed
│ nodeids
│ stepwise
│
├───src
│ │ main.py
│ │ setup.py
│ │ __init__.py
│ │
│ ├───alembic
│ │ │ env.py
│ │ │ script.py.mako
│ │ │
│ │ ├───versions
│ │ │ └───__pycache__
│ │ │ 3d6ca513c0f2_initial.cpython-311.pyc
│ │ │ d9fa35d931d1_.cpython-311.pyc
│ │ │
│ │ └───__pycache__
│ │ env.cpython-311.pyc
│ │
│ ├───api
│ │ │ __init__.py
│ │ │
│ │ ├───v1
│ │ │ │ __init__.py
│ │ │ │
│ │ │ ├───wallets
│ │ │ │ │ wallet_router.py
│ │ │ │ │ __init__.py
│ │ │ │ │
│ │ │ │ └───__pycache__
│ │ │ │ wallet_router.cpython-311.pyc
│ │ │ │ __init__.cpython-311.pyc
│ │ │ │
│ │ │ └───__pycache__
│ │ │ __init__.cpython-311.pyc
│ │ │
│ │ └───__pycache__
│ │ __init__.cpython-311.pyc
│ │
│ ├───database
│ │ │ session.py
│ │ │ __init__.py
│ │ │
│ │ └───__pycache__
│ │ session.cpython-311.pyc
│ │ __init__.cpython-311.pyc
│ │
│ ├───models
│ │ │ wallet_model.py
│ │ │ __init__.py
│ │ │
│ │ └───__pycache__
│ │ wallet_model.cpython-311.pyc
│ │ __init__.cpython-311.pyc
│ │
│ ├───schemas
│ │ │ base_schema.py
│ │ │ wallet_schema.py
│ │ │ __init__.py
│ │ │
│ │ └───__pycache__
│ │ wallet_schema.cpython-311.pyc
│ │ __init__.cpython-311.pyc
│ │
│ ├───services
│ │ │ wallet_service.py
│ │ │ __init__.py
│ │ │
│ │ └───__pycache__
│ │ wallet_service.cpython-311.pyc
│ │ __init__.cpython-311.pyc
│ │
│ ├───wallet_api.egg-info
│ │ dependency_links.txt
│ │ PKG-INFO
│ │ requires.txt
│ │ SOURCES.txt
│ │ top_level.txt
│ │
│ └───__pycache__
│ main.cpython-311.pyc
│ __init__.cpython-311.pyc
│
└───tests
│ conftest.py
│ test_wallet_api.py
│ __init__.py
│
├───.pytest_cache
│ │ .gitignore
│ │ CACHEDIR.TAG
│ │ README.md
│ │
│ └───v
│ └───cache
│ lastfailed
│ nodeids
│ stepwise
│
└───__pycache__
conftest.cpython-311-pytest-8.3.4.pyc
conftest.cpython-311-pytest-8.3.5.pyc
test_wallet_api.cpython-311-pytest-8.3.4.pyc
test_wallet_api.cpython-311-pytest-8.3.5.pyc
__init__.cpython-311.pyc
Ответы (1 шт):
Автор решения: DD Alter
→ Ссылка
Прошерстив интернет я узнал, что если таблица уже создана, то миграция изначальна будет пустой. Почему я не обратил на это внимание? Потому что подумал, что если БД хоть и создана, но пустая, то миграции все равно задетектят таблицы, но нет. Решил проблему удалением таблицы (благо это была тестовая таблица). После этого все заработало и alembic задетектил всё что нужно.