问题
I have this tree in my flask application:
-- api
-- migrations
-- model
-- __init__.py
-- Persons.py
-- Comments.py
-- other_classes.py
-- resources
-- __init__.py
-- app.py
-- util.py
This is __init_.py
from model directory:
from os.path import dirname, basename, isfile
import glob
modules = glob.glob(dirname(__file__)+"/*.py")
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
from .Persons import Persons
This is util.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
import os
import model
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_ENGINE'] + '://' + \
os.environ['DATABASE_USERNAME'] + ':' + \
os.environ['DATABASE_PASSWORD'] + '@' + \
os.environ['DATABASE_SERVER'] + '/api_rest?charset=utf8'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
return app
app = create_app()
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
this is app.py
from util import app
from flask import Flask, jsonify
from flask_restful import reqparse, abort, Api, Resource
@app.errorhandler(404)
def not_found(e):
return jsonify({'message' : 'Not Found'}), 404
@app.errorhandler(500)
def internal_server_error(e):
return jsonify({'message' : 'Internal Server Error'}), 500
api = Api(app)
class Overview(Resource):
def get(self):
return {'hello': 'world'}
api.add_resource(Overview, '/v1/api/overview')
if __name__ == '__main__':
app.run( host = '0.0.0.0', port = 5000, debug = True, threaded = True )
Persons.py
# coding=utf-8
import sys
import os
from flask_sqlalchemy import SQLAlchemy
sys.path.append(os.path.dirname(os.getcwd()))
db = SQLAlchemy()
class Persons(db.Model):
id = db.Column( db.Integer, primary_key = True )
name = db.Column( db.String(255) )
firstname = db.Column( db.String(255) )
lastname = db.Column( db.String(255) )
When I do python3.6 util.py db migrate
, the classes inside model folder are not detected:
INFO [sqlalchemy.engine.base.Engine] SHOW VARIABLES LIKE 'sql_mode'
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SELECT DATABASE()
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] show collation where `Charset` = 'utf8' and `Collation` = 'utf8_bin'
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin AS anon_1
INFO [sqlalchemy.engine.base.Engine] ()
INFO [alembic.runtime.migration] Context impl MySQLImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [sqlalchemy.engine.base.Engine] DESCRIBE `alembic_version`
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SELECT alembic_version.version_num
FROM alembic_version
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] DESCRIBE `alembic_version`
INFO [sqlalchemy.engine.base.Engine] ()
INFO [sqlalchemy.engine.base.Engine] SHOW FULL TABLES FROM `dsiapi_rest`
INFO [sqlalchemy.engine.base.Engine] ()
INFO [alembic.env] No changes in schema detected.
I have looked in the other questions but I can't find any clue. Is the structure of the API correct? I have so many tables and I split them in files. When I put them directly inside util.py the migration works. but I don't want to put everything in one single file. That's why I need to put each table in a single file inside the folder /model
.
Please help
thank you
EDIT I also tried this:
MODELS_DIRECTORY = "models"
EXCLUDE_FILES = ["__init__.py"]
def import_models():
for dir_path, dir_names, file_names in os.walk(MODELS_DIRECTORY):
for file_name in file_names:
if file_name.endswith("py") and not file_name in EXCLUDE_FILES:
file_path_wo_ext, _ = os.path.splitext((os.path.join(dir_path, file_name)))
module_name = file_path_wo_ext.replace(os.sep, ".")
importlib.import_module(module_name)
It didn't detect the model classes.
I think the problem is that I don't use the same db variable in util as in the models. Even when I do inside the model classes:
from util import db
it doesn't change anything
I have seen examples around but none of them has as much models in them. When we have too many tables it's not a good practice to put all of them in one file. Splitting them and making them inside a folder is a good idea but it doesn't seem working.
回答1:
I think you are on the right track. First of all, you need to use the same db
across your entire application. I would keep the one in util.py and remove all others.
After that, you need to make sure that when you run util.py the models are imported. I see that you are trying clever ways to get all your models imported into your model
package. I favor doing explicit imports of all your models instead of this type of automatic imports, so my recommendation is that you just import the models one by one.
The final thing you should do to make sure your models are recognized is to delete or move away your SQLite database. When you run the db migrate
command after you removed the database file, you should get a migration with everything in it.
回答2:
You aren't importing the models
db = SQLAlchemy(app)
# import the models
migrate = Migrate(app, db)
If that doesn't help review this issue.
https://github.com/miguelgrinberg/Flask-Migrate/issues/50
来源:https://stackoverflow.com/questions/54632694/models-are-not-detectable-by-flask-migrate