Alembic试图删除我的表

coo*_*les 1 python sqlalchemy alembic

Alembic初学者在这里。我在尝试删除已创建的表时遇到一些与Alembic有关的问题。我不知道发生了什么。现在我有一个数据库,看起来像这样:

在此处输入图片说明

如果运行alembic upgrade head,我将得到以下结果:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
Run Code Online (Sandbox Code Playgroud)

如果我运行alembic history,则会得到以下结果,这是正确的:

c2659db918a9 -> 765c30f7078c (head), creat table views
c4a0cac54f89 -> c2659db918a9, Made last_update not null for all tables
19dd9f3d1d16 -> c4a0cac54f89, Added last_update field defaulted to now
77c03ebb393b -> 19dd9f3d1d16, Added indexes to each table
0737825277d8 -> 77c03ebb393b, Change foreign key columns to non-nullable
5eb3c5f7f599 -> 0737825277d8, Rename a column in daily_etf_underlying table
0da0b2a43172 -> 5eb3c5f7f599, Add extra_info column to daily_etf_underlying
c181fe8bcfa9 -> 0da0b2a43172, Make daily_etf id columns nullable
8fba2675104b -> c181fe8bcfa9, added fixing table
074563d69c3b -> 8fba2675104b, Modify daily_etf tables
2c9de57e43f0 -> 074563d69c3b, Add fund_family columns
80de6fb0a104 -> 2c9de57e43f0, Modify daily_etf table
a970af9bb117 -> 80de6fb0a104, Add daily_etf_basket, daily_etf_fx_forward tables
<base> -> a970af9bb117, Add daily_etf table
Run Code Online (Sandbox Code Playgroud)

但是如果我跑步alembic revision --autogenerate -m "<>",我会得到的!

alembic revision --autogenerate -m "Raw fidessa client trade table"
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.ddl.postgresql] Detected sequence named 'daily_etf_fx_forward_id_seq' as owned by integer column 'daily_etf_fx_forward(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed table 'daily_etf_fx_forward'
INFO  [alembic.autogenerate.compare] Detected removed table 'daily_etf'
INFO  [alembic.ddl.postgresql] Detected sequence named 'daily_fx_fixing_rate_id_seq' as owned by integer column 'daily_fx_fixing_rate(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed table 'daily_fx_fixing_rate'
INFO  [alembic.ddl.postgresql] Detected sequence named 'daily_etf_underlying_id_seq' as owned by integer column 'daily_etf_underlying(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed table 'daily_etf_underlying'
Generating C:\dev\Projects\stark_database\stark_database\migrations\versions\86174c06e59e_raw_fidessa_client_trade_table.py ... done
Run Code Online (Sandbox Code Playgroud)

我的自动生成的文件只是试图删除我所有的表:(

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('daily_fx_fixing_rate')
    op.drop_table('daily_etf_underlying')
    op.drop_table('daily_etf')
    op.drop_table('daily_etf_fx_forward')
    # ### end Alembic commands ###
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?为什么Alembic试图删除所有内容?

谢谢你的帮助。

编辑alembic.ini

[alembic]
script_location = migrations
sqlalchemy.url = postgresql://stark_admin:hpt@localhost/stark
Run Code Online (Sandbox Code Playgroud)

env.py 正是教科书 alembic init alembic

coo*_*les 5

我想通了。该metadata对象不正确。

对于那些阅读,

确保您输入的是正确metadatatarget_metadata = metadata。如果数据库中已经有一些表,并且按照注释中的Ilja的建议提供了新表metadataNone元数据,则会看到此行为,因为Alembic知道基于该元数据,这些表不应在数据库中,因此它将尝试删除那些。

此外,通常您会在的不同文件中包含类SQLAlchemy。对于这个工作,你必须确保你使用的是相同metadataBase整个文件的实例。否则,您将获得不检测表或尝试删除现有表的行为。

这是后一种情况的示例:

假设我有一个像

database
    /migrations
        /versions
            1348ht31r3_first_migration.py
        env.py
        README
        script.py.mako
    /models
        __init__.py
        a_class.py
Run Code Online (Sandbox Code Playgroud)

在中__init__.py,我执行以下典型操作declarative_base()

# __init__.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
engine = create_engine('url')
Run Code Online (Sandbox Code Playgroud)

然后在中a_class.py,我有我的模型类,其父类是__init__.py

from datetime import datetime

from sqlalchemy import Column, Integer, String, Float
from sqlalchemy import Date, DateTime
from sqlalchemy import ForeignKey
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import relationship

from stark_database.models import Base


class AClass(Base):
    __tablename__ = 'a_class'
    id = Column(Integer, primary_key=True)
    insert_date = Column(Date)
    symbol = Column(String)
    pnu = Column(Float)
    projected_shares_outstanding = Column(Float)
    shares_outstanding = Column(Float)
    projected_nav = Column(Float)
    nav = Column(Float)
    basket_cash_per_currency = Column(JSONB)
    fund_cash_per_currency = Column(JSONB)
    info_type = Column(String)
    fund_family = Column(String)
    last_updated = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
Run Code Online (Sandbox Code Playgroud)

这是正确的,但是在中env.py,您必须确保导入Base类模型。

from __future__ import with_statement

import os
import sys
from logging.config import fileConfig

from alembic import context
from sqlalchemy import engine_from_config, pool

# DO NOT DELETE THIS LINE. 
from database.models import Base, a_class
Run Code Online (Sandbox Code Playgroud)

alembic在我看来,这不是问题,但有点像python陷阱。

希望这可以帮助。

  • 只是一点额外的一点,您可以只“导入database.models”,而不必枚举所有模型。这意味着您不必每次添加模型时都编辑 env.py(假设所有 SQLAlchemy 模型都位于一个文件中)。 (4认同)
  • 有关该主题的相关文档:http://alembic.zzzcomputing.com/en/latest/autogenerate.html (2认同)