J'ai les modèles suivants dans le fichier listpull/models.py
:
from datetime import datetime
from listpull import db
class Job(db.Model):
id = db.Column(db.Integer, primary_key=True)
list_type_id = db.Column(db.Integer, db.ForeignKey('list_type.id'),
nullable=False)
list_type = db.relationship('ListType',
backref=db.backref('jobs', lazy='dynamic'))
record_count = db.Column(db.Integer, nullable=False)
status = db.Column(db.Integer, nullable=False)
sf_job_id = db.Column(db.Integer, nullable=False)
created_at = db.Column(db.DateTime, nullable=False)
compressed_csv = db.Column(db.LargeBinary)
def __init__(self, list_type, created_at=None):
self.list_type = list_type
if created_at is None:
created_at = datetime.utcnow()
self.created_at = created_at
def __repr__(self):
return '<Job {}>'.format(self.id)
class ListType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
def __init__(self, name):
self.name = name
def __repr__(self):
return '<ListType {}>'.format(self.name)
J'appelle ./run.py init
puis ./run.py migrate
puis ./run.py upgrade
et je vois le fichier de migration généré, mais vide:
"""empty message
Revision ID: 5048d48b21de
Revises: None
Create Date: 2013-10-11 13:25:43.131937
"""
# revision identifiers, used by Alembic.
revision = '5048d48b21de'
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 ###
run.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from listpull import manager
manager.run()
listpull/__ init__.py
# -*- coding: utf-8 -*-
# pylint: disable-msg=C0103
""" listpull module """
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand
from mom.client import SQLClient
from smartfocus.restclient import RESTClient
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
mom = SQLClient(app.config['MOM_Host'],
app.config['MOM_USER'],
app.config['MOM_PASSWORD'],
app.config['MOM_DB'])
sf = RESTClient(app.config['SMARTFOCUS_URL'],
app.config['SMARTFOCUS_LOGIN'],
app.config['SMARTFOCUS_PASSWORD'],
app.config['SMARTFOCUS_KEY'])
import listpull.models
import listpull.views
METTRE &AGRAVE; JOUR
Si j'exécute le shell via ./run.py Shell
, puis que je fais from listpull import *
et appelle db.create_all()
, je reçois le schéma:
mark.richman@MBP:~/code/nhs-listpull$ sqlite3 app.db
-- Loading resources from /Users/mark.richman/.sqliterc
SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
CREATE TABLE job (
id INTEGER NOT NULL,
list_type_id INTEGER NOT NULL,
record_count INTEGER NOT NULL,
status INTEGER NOT NULL,
sf_job_id INTEGER NOT NULL,
created_at DATETIME NOT NULL,
compressed_csv BLOB,
PRIMARY KEY (id),
FOREIGN KEY(list_type_id) REFERENCES list_type (id)
);
CREATE TABLE list_type (
id INTEGER NOT NULL,
name VARCHAR(80) NOT NULL,
PRIMARY KEY (id),
UNIQUE (name)
);
sqlite>
Malheureusement, les migrations ne fonctionnent toujours pas.
Lorsque vous appelez la commande migrate
, Flask-Migrate (ou réellement Alembic en dessous) examine votre models.py
et le compare à ce qui se trouve réellement dans votre base de données.
Le fait que vous ayez un script de migration vide suggère que vous avez mis à jour votre base de données pour l'adapter à votre modèle via une autre méthode en dehors du contrôle de Flask-Migrate, par exemple en appelant la fonction db.create_all()
de Flask-SQLAlchemy.
Si vous ne disposez pas de données précieuses dans votre base de données, ouvrez un shell Python et appelez db.drop_all()
pour le vider, puis relancez la migration automatique.
UPDATE: J'ai installé votre projet ici et confirmé que les migrations fonctionnent correctement pour moi:
(venv)[miguel@miguel-linux nhs-listpull]$ ./run.py db init
Creating directory /home/miguel/tmp/mark/nhs-listpull/migrations...done
Creating directory /home/miguel/tmp/mark/nhs-listpull/migrations/versions...done
Generating /home/miguel/tmp/mark/nhs-listpull/migrations/script.py.mako...done
Generating /home/miguel/tmp/mark/nhs-listpull/migrations/env.pyc...done
Generating /home/miguel/tmp/mark/nhs-listpull/migrations/env.py...done
Generating /home/miguel/tmp/mark/nhs-listpull/migrations/README...done
Generating /home/miguel/tmp/mark/nhs-listpull/migrations/alembic.ini...done
Please edit configuration/connection/logging settings in
'/home/miguel/tmp/mark/nhs-listpull/migrations/alembic.ini' before
proceeding.
(venv)[miguel@miguel-linux nhs-listpull]$ ./run.py db migrate
INFO [alembic.migration] Context impl SQLiteImpl.
INFO [alembic.migration] Will assume non-transactional DDL.
INFO [alembic.autogenerate] Detected added table 'list_type'
INFO [alembic.autogenerate] Detected added table 'job'
Generating /home/miguel/tmp/mark/nhs-
listpull/migrations/versions/48ff3456cfd3_.py...done
Essayez une nouvelle caisse, je pense que votre configuration est correcte.
Assurez-vous d’importer les modèles dans le fichier manage.py
(ou dans le fichier avec l’instance migrate). Vous devez importer les modèles dans le fichier, même si vous ne les utilisez pas explicitement. Alembic a besoin de ces importations pour migrer et créer les tables dans la base de données. Par exemple:
# ... some imports ...
from api.models import User, Bucketlist, BucketlistItem # Import the models
app = create_app('dev')
manager = Manager(app)
migrate = Migrate(app, db)
manager.add_command('db', MigrateCommand)
# ... some more code here ...
if __== "__main__":
manager.run()
db.create_all()
Je viens de rencontrer un problème similaire. Je voudrais partager ma solution pour quiconque rencontre ce fil. Pour moi, j'avais mes modèles dans un paquet. Par exemple, models/user.py et moi avons essayé from app.models import *
qui n'a rien détecté lors de la migration. Cependant, si je modifiais l’importation en from app.models import user
, c’était bien pourquoi mon projet était jeune, mais comme je disposais de plus de modèles, une importation en bloc serait préférable.
J'avais le même problème, mais un problème différent le causait. Le flux de travail Flask-migrate se compose de deux commandes conséquentes:
flask db migrate
qui génère la migration et
flask db upgrade
qui applique la migration. J'ai oublié d'exécuter la dernière et j'ai essayé de lancer la prochaine migration sans appliquer la précédente.
Pour tous ceux qui venaient à travers cela, mon problème était d'avoir
db.create_all()
dans mon dossier de demande de flacon principal qui a créé la nouvelle table à l’insu de alambic
Commentez-le simplement ou supprimez-le complètement pour ne pas déranger les migrations futures.
mais contrairement à la suggestion de @ Miguel, au lieu de supprimer toute la base de données (j'avais des informations importantes), j'ai pu résoudre le problème en supprimant la nouvelle table créée par Flask SQLAlchemy, puis en exécutant la migration.
et cette fois, alembic a détecté la nouvelle table et a créé un script de migration approprié
Étrange résoudre pour moi est: supprimer la base de données et le dossier migrations
. ensuite
>>> from app import db
>>> db.create_all()
Après flask db init
ou python app.py db init
et ensuite flask db migrate
ou python app.py db migrate
. Wow, c'est étrange, mais ça marche pour moi.