问题
Alembic beginner here. I'm having some issues with Alembic trying to delete my tables that are already created. I have no idea what is going on. Right now I have a database that looks like this:
If I run alembic upgrade head
, I get this as my result:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
If I run alembic history
, I get this result, which is correct:
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
But if I run alembic revision --autogenerate -m "<>"
, I get this!
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
And my autogenerated file is just trying to remove all my tables :(
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 ###
What is going on here? Why is alembic trying to delete everything?
Thanks for your help.
EDIT: alembic.ini
:
[alembic]
script_location = migrations
sqlalchemy.url = postgresql://stark_admin:hpt@localhost/stark
env.py
is exactly textbook to alembic init alembic
回答1:
I figured out. The metadata
object was incorrect.
For those reading,
Make sure you have the correct metadata
in target_metadata = metadata
. If you have some tables already in the database and you supply a new metadata
or a None
metadata as Ilja suggested in the comments, you will see this behavior because alembic knows that based on that metadata, those tables should not be in the database, so it will try to delete those.
Moreover, typically you will have classes in different files for SQLAlchemy
. For this to work, you have to make sure that you are using the same metadata
or Base
instance across the files. Otherwise, you will get this behavior of not detecting tables or trying to delete existing tables.
Here's an example of the latter situation:
Suppose I have a structure like
database
/migrations
/versions
1348ht31r3_first_migration.py
env.py
README
script.py.mako
/models
__init__.py
a_class.py
In __init__.py
, I do the typical declarative_base()
:
# __init__.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('url')
And then in a_class.py
, I have my model class whose parent class is the Base from __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)
This is correct, but in env.py
, you have to make sure you import the Base class and the model.
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
This isn't an alembic
thing but it's a bit of a python gotcha in my opinion.
Hope this helps.
来源:https://stackoverflow.com/questions/45695008/alembic-trying-to-delete-my-tables