alembic autogenerates создает пустую миграцию, но генерирует таблицу

Я следовал документации от Alembic для автоматического создания миграции. Структура моего проекта выглядит так:

alembic/
  versions/
  env.py
  README
  script.py.mako
data/
  __init__.py
  db.py
  models.py
alembic.ini
app.db

Я внес изменения в env.py, точно следуя документу:

from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context
from data.models import Base

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata

# 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.


def run_migrations_offline():
    """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():
    """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()

Это мой __init__.py:

import os

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from .models import Base

basedir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
db_url = os.environ.get('DATABASE_URL') or \
         'sqlite:///' + os.path.join(basedir, 'app.db')
engine = create_engine(db_url, echo=False)
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)

Я создал класс пользователя в models.py следующим образом:

from sqlalchemy import Column, Sequence, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()    

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, Sequence('id_seq'), primary_key=True)
    first_name = Column(String, nullable=False)
    last_name = Column(String, nullable=False)

    def __repr__(self):
        return "<%s('%s', '%s')>" \
               % (self.__class__.__qualname__, self.first_name,
                  self.last_name)

После этого я запускаю миграцию:

alembic revision --autogenerate -m "Added user table"

Однако я получил пустые обновления() и понижение() в файле миграции:

"""Added user table

Revision ID: 279933caec54
Revises: 
Create Date: 2021-05-12 16:21:05.772568

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '279933caec54'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    pass
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    pass
    # ### end Alembic commands ### 

Но когда я проверил базу данных, там была создана пользовательская таблица (сам я этого не делал). Как это случилось? Как alembic создал пустую миграцию, но создал таблицу?


person Tyrion    schedule 12.05.2021    source источник


Ответы (1)


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

Итак, как было предложено в ответе, я прокомментировал Base.metadata.create_all(engine) в __init__.py. Именно эта строка кода создает пользовательскую таблицу (если она не существует). Итак, когда alembic проверяет мою базу данных, таблица уже там. Поскольку различий не обнаружено, функции upgrade() и downgrade() пусты.

person Tyrion    schedule 12.05.2021