Alembic 试图删除我的表格

问题描述 投票:0回答:2

这里是蒸馏器初学者。我在使用 Alembic 尝试删除已创建的表时遇到一些问题。我不知道发生了什么事。现在我有一个如下所示的数据库:

如果我运行

alembic upgrade head
,我得到的结果是:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.

如果我运行

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

但是如果我运行

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

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

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

这是怎么回事?为什么 Alembic 试图删除所有内容?

感谢您的帮助。

编辑:

alembic.ini

[alembic]
script_location = migrations
sqlalchemy.url = postgresql://stark_admin:hpt@localhost/stark

env.py
完全就是教科书
alembic init alembic

python sqlalchemy alembic
2个回答
25
投票

我想通了。

metadata
对象不正确。

对于那些正在阅读的人,

确保

metadata
中的
target_metadata = metadata
正确。如果数据库中已有一些表,并且按照 Ilja 在评论中建议的那样提供了新的
metadata
None
元数据,您将看到此行为,因为 alembic 知道根据该元数据,这些表不应位于数据库,因此它将尝试删除它们。

此外,通常您会在不同的文件中拥有

SQLAlchemy
的类。为此,您必须确保在文件中使用相同的
metadata
Base
实例。否则,您将出现未检测到表或尝试删除现有表的行为。

这是后一种情况的示例:

假设我有这样的结构

database
    /migrations
        /versions
            1348ht31r3_first_migration.py
        env.py
        README
        script.py.mako
    /models
        __init__.py
        a_class.py

__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')

然后在

a_class.py
中,我有我的模型类,其父类是来自
__init__.py

的Base
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)

这是正确的,但在

env.py
中,您必须确保导入基类模型。

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

这不是一个

alembic
的事情,但在我看来这是一个Python陷阱。

希望这有帮助。


0
投票

尽管这是 6 年前的事,但我自己也遇到过这个问题。 我有一个包含所有模型的 models.py,并且在 target_metadata 的 env.py 配置中,我注意到该变量没有被声明下方定义的函数 get_metadata 使用,因此我从该函数和所有内容返回了它正在工作。

# for 'autogenerate' support
from models import Base
target_metadata = 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.

def get_metadata():
    return target_metadata # ADD THIS LINE 
    if hasattr(target_db, 'metadatas'):
        return target_db.metadatas[None]
    return target_db.metadata

© www.soinside.com 2019 - 2024. All rights reserved.