Python 使用Blueprint中的元数据创建Flask SQLAlchemy实例

Python 使用Blueprint中的元数据创建Flask SQLAlchemy实例,python,flask,sqlalchemy,flask-sqlalchemy,python-import,Python,Flask,Sqlalchemy,Flask Sqlalchemy,Python Import,TL;DR:如何使用蓝图中的元数据对象创建Flask SQLAlchemy实例?我能看到的提供声明性基本元数据对象的唯一地方是初始的SQLAlchemy()调用。但是,当我从extensions.py文件中的Blueprint导入它时,Blueprint的代码需要db对象,并且由于循环导入,加载失败 $ flask db migrate Error: While importing "my_app", an ImportError was raised: Traceback (most rec

TL;DR:如何使用蓝图中的
元数据
对象创建Flask SQLAlchemy实例?我能看到的提供声明性基本元数据对象的唯一地方是初始的
SQLAlchemy()
调用。但是,当我从
extensions.py
文件中的Blueprint导入它时,Blueprint的代码需要
db
对象,并且由于循环导入,加载失败

$ flask db migrate
Error: While importing "my_app", an ImportError was raised:

Traceback (most recent call last):
  File "my_app/venv/lib/python3.7/site-packages/flask/cli.py", line 235, in locate_app
    __import__(module_name)
  File "my_app/my_app.py", line 1, in <module>
    from app import create_app
  File "my_app/app/__init__.py", line 7, in <module>
    from app.extensions import *
  File "my_app/app/extensions.py", line 10, in <module>
    from turf.models import metadata
  File "my_app/turf/__init__.py", line 1, in <module>
    from .routes import bp
  File "my_app/turf/routes.py", line 14, in <module>
    from app.extensions import db
ImportError: cannot import name 'db' from 'app.extensions' (my_app/app/extensions.py)


我有几个模型类,我想在Flask内外使用它们。我正在使用它,我的应用程序设置为使用应用程序工厂模型和蓝图。使用SQLAlchemy注册模型的方法是在创建
db
对象时使用
metadata
参数。在我的应用程序上下文中,在蓝图中而不是在主应用程序蓝图中声明
元数据
对象是有意义的。(这就是引用它的大多数代码所在的位置,包括最初用于填充数据库的非Flask实用程序脚本。)但是,从第二个蓝图导入模型类最终以循环导入结束

$ flask db migrate
Error: While importing "my_app", an ImportError was raised:

Traceback (most recent call last):
  File "my_app/venv/lib/python3.7/site-packages/flask/cli.py", line 235, in locate_app
    __import__(module_name)
  File "my_app/my_app.py", line 1, in <module>
    from app import create_app
  File "my_app/app/__init__.py", line 7, in <module>
    from app.extensions import *
  File "my_app/app/extensions.py", line 10, in <module>
    from turf.models import metadata
  File "my_app/turf/__init__.py", line 1, in <module>
    from .routes import bp
  File "my_app/turf/routes.py", line 14, in <module>
    from app.extensions import db
ImportError: cannot import name 'db' from 'app.extensions' (my_app/app/extensions.py)

以及因循环导入而失败的相关代码:

app/\uuuu init\uuuuu.py:

app/extensions.py:

草皮/uuuuuuuuuuuuuuuuuuuuu.py:

草皮/models.py:

草皮/路线.py:


事实证明,您可以在
extensions.py
文件中声明元数据对象,然后将其导入Blueprint。我确信这会失败,因为
元数据
对象现在是在创建
db
对象之后填充的,但是我已经验证了模型确实可用并且按照预期工作。不再有循环依赖。实际上,我已经将这个部分分解到它自己的文件中,以便尽可能少地导入Blueprint代码

app/base.py:

app/extensions.py:

草皮/models.py:

这也回答了我最初的方法中的另一个问题:如果我有第二个蓝图,其中也有需要从非Flask代码中获得的模型对象,它将如何工作?现在,我已经创建了一个基本对象,可以根据需要在不同的蓝图中实现新的类

不过,这种方法有一个小麻烦。在非Flask DB填充脚本中,我最初能够使用
from models import*
引用包含模型的同级模块(文件)。这让我直接调用脚本,即la
cd-turp;python填充_db.py--arg
。这不再有效,因为
models.py
文件现在引用了另一个包
app.extensions
。因此,我必须使用以下解决方法:

草皮/填充_db.py:


请总结一下你的写作。这更像是写一篇文章。我已经添加了一个摘要,谢谢。如果我在初始化扩展后注册蓝图,部分问题就解决了。Flask随后将运行,但Flask_migrate(Alembic)仍在抱怨。(事实证明并非如此。
Flask run
仍然失败,出现相同的循环导入错误。不知道为什么它在重新加载时工作了一段时间,然后停止。)
from app.extensions import *

def create_app():
    app = Flask(__name__)

    with app.app_context():
        import turf
        app.register_blueprint(turf.bp)

        db.init_app(app)

from turf.models import metadata

db = SQLAlchemy(metadata=metadata)
from .routes import bp
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import MetaData

metadata = MetaData()
Base = declarative_base(metadata=metadata)

# All the turf models are declared in this file
class Boundary(Base):
    # ...etc...
from .models import *
from app.extensions import db

bp = Blueprint('Turf', __name__, url_prefix='/turf')

@bp.route('/')
def index():
    return render_template('turf/index.html')
from sqlalchemy import MetaData
from sqlalchemy.ext.declarative import declarative_base

metadata = MetaData()
Base = declarative_base(metadata=metadata)
from flask_sqlalchemy import SQLAlchemy
from .base import metadata

db = SQLAlchemy(metadata=metadata)
from app.base import Base

# All the turf models are declared in this file
class Boundary(Base):
    # ...etc...
try:
    from .models import *
except:
    print("You have to run this from outside the 'turf' directory like so: $ python -m turf.populate_db [...]")
    sys.exit(1)