web-dev-qa-db-fra.com

Flask-Migrate ne crée pas de tables

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.

17
Mark Richman

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.

13
Miguel

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()
8
wcyn

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. 

7
matchew

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.

6
Dany

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é

5
danidee

É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.

0
kot_mapku3