2013-06-19 13 views
10

Używam Alembic do obsługi migracji dla Flask. alembic revision --autogenerate powinien, w teorii, automatycznie generować migrację na podstawie zmian w mojej bazie danych. Jednak Alembic po prostu generuje pustą migrację za pomocą powyższego polecenia.Alembik automatycznie generuje puste migracje Flask-SQLAlchemy

Istnieje numer question very similar to this one, w którym problem polegał na tym, że odpowiednie modele nie były importowane. Mam jednak importowane modele z mojego Kolby aplikacji, jak pokazano na env.py:

... 
# import settings from Flask 
alembic_config = config.get_section(config.config_ini_section) 
from start import app 
from models import User, Item, Recipient # models are imported here from models.py 
alembic_config['sqlalchemy.url'] = app.config['SQLALCHEMY_DATABASE_URI'] 

engine = engine_from_config(
      alembic_config, # config.get_section(config.config_ini_section) 
      prefix='sqlalchemy.', 
      poolclass=pool.NullPool) 
... 

jak również importowane metadane dB env.py („start” to nazwa głównego pliku mojego kolby aplikacji):

... 
from start import db 
target_metadata = db.metadata 
... 

Running alembic revision --autogenerate -m "initial_rev" następnie generuje pusty migracji, choć mój Kolba aplikacja będzie mieć odmienne zdanie:

"""initial_rev 

Revision ID: 45296fd29540 
Revises: None 
Create Date: 2013-06-19 17:32:38.392268 

""" 

# revision identifiers, used by Alembic. 
revision = '45296fd29540' 
down_revision = None 

from alembic import op 
import sqlalchemy as sa 


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

Edycja

Here is a gist pokazuje strukturę plików mojej aplikacji, a także dodatkowy kod. Wydaje się, że problem polega na tym, że Alembic nie lubi, aby db był importowany z database.py bez pierwszego zainicjowania w __init__.py. Nie jest to jednak możliwe , gdy używane są plany (z powodu cyklicznych importów), wyjaśnione w tej odpowiedzi WR: https://stackoverflow.com/a/9695045/353878.

Pytanie brzmi, w jaki sposób można używać Alembic, gdy stosowane są również schematy Flask?

Edit # 2

Próbowałem nawet drukowania db.metadata.sorted_tables, aby upewnić się, że metadane bazy danych został importowany poprawnie. Rzeczywiście, cały schemat bazy danych został podłączony do terminala. Dlaczego więc Alembic generuje puste funkcje aktualizacji/obniżenia wersji?

Edit # 3

mam stwierdziła, że ​​sprawa ma coś wspólnego z różnicami db.init_app(app) i db = SQLAlchemy(app), ale nie jestem pewien, co jest przyczyną problemu. Aby przetestować tę teorię, zastąpiłem from database import db w env.py na db = SQLAlchemy(app). Prawdopodobnie zły pomysł, ale chciałem zobaczyć, co się stanie z debugowaniem.

Alembic automatycznie wygenerował i wypełnił metody upgrade() i downgrade() - z tą różnicą, że zostały odwrócone! upgrade() usunąłem wszystkie trzy moje tabele, podczas gdy downgrade() utworzyłem je ze wszystkimi właściwymi kolumnami i metadanymi. Nie mam pojęcia, dlaczego tak jest, ale mam nadzieję, że jest to pomocne dla osób próbujących zrozumieć ten problem.

+0

W jaki sposób zmienił się twój schemat po uruchomieniu 'alembic revision --autogenerate'? – drewman

+0

Dodałem trzy tabele z kilkoma kolumnami. – element119

+0

należy zaimportować modele w pliku 'env.py', aby zarejestrować się w metadanych. – iElectric

Odpowiedz

23

Oto jak używam Alembic z kolbą i planami.

https://github.com/davidism/basic_flask

używam aplikacji fabryczny wzór i zadzwonić db.init_app w tym. Po db = SQLAlchemy() importuję wszystkie modele, które mają podklasę db.Model, dzięki czemu db.metadata jest tego świadomy; zauważ, że nie jest to robione w fabryce create_app, ale po prostu wstawiane podczas init modułu.

Po uruchomieniu alembic folder projektu nie jest zawarty w sys.path, więc ustawiłem go. Następnie tworzę aplikację z fabryki i ustawię sqlalchemy.url z jej konfiguracji. Ponadto importuję numer db i ustawię target_metadata = db.metadata.

Ta konfiguracja działa dla mnie przez cały czas, bez względu na strukturę projektu. Zawarłem bardzo prosty zestaw modeli użytkowników i bardzo głupi widok w podpakietie z planem. Wystarczy załadować modele relavent w load_models, zaimportować widoki po zdefiniowaniu planu i zaimportować plany w init_views.

+0

Dziękuję bardzo za odpowiedź! Próbowałem wprowadzić zmiany, które zasugerowałeś, ale mam dwa pytania: kiedy wywoływana jest funkcja init_views()? Ponadto, w tej konfiguracji, w jaki sposób masz nadal metody appwide (np. @ App.before_request)? – element119

+0

@autibyte 'init_views' jest wywoływane w' create_app'. Podobne do 'init_views' możesz utworzyć' init_helpers', aby zarejestrować te, gdy tworzona jest aplikacja. – davidism

Powiązane problemy