【问题标题】:How to create flask-sqlalchemy tables with models in blueprints?如何使用蓝图中的模型创建 flask-sqlalchemy 表?
【发布时间】:2021-08-21 00:59:25
【问题描述】:

我正在 Python 3.9 中使用 flask y flask-sqlalchemy 开发应用程序。

首先,我创建了一个简单的小型应用程序(没有蓝图),为用户提供一个模型。

db.create_all() 工作没有问题。

我扩展了应用程序并决定将其划分为蓝图。应用程序和与数据库的连接仍然正常工作:用户可以登录。

所以,我决定创建另一个模型,但 db.create_all() 没有工作。未创建新表。而且,清空数据库后,第一个用户表也没有创建。

我在网上看过几篇帖子,问题是需要导入模型,或者缺少app上下文:

with app.app_context():
   db.create_all()

即使模型被导入并在应用程序的上下文中执行,也不会创建表。

另一方面,如果我复制模型的类并将其粘贴到运行db.create_app() 的文件中,则会创建表。据我了解,这是如何导入模型或如何定义蓝图的问题。 SQLAlchemy 不检测模型。

[entrypoint.py] 这行得通:

import numpy as np
from app import create_app, db
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

class User(db.Model, UserMixin):

    __tablename__ = 'it_user'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(32), unique=True, nullable=False)
    email = db.Column(db.String(256), unique=True, nullable=True)
    password = db.Column(db.String(256), nullable=False)

    def __repr__(self):
        return '<User {}:{}>'.format(self.id, self.username)


    def save(self):
        if not self.id:
            db.session.add(self)
        db.session.commit()

    ....

class Simulation(db.Model):

    __tablename__ = 'it_simulation'

    id = db.Column(db.Integer, primary_key=True)
    symbol = db.Column(db.String(10), nullable=False)
    date = db.Column(db.Date(), nullable=False)
    simulations = db.Column(db.Integer(), nullable=False)
    predictions = db.Column(db.ARRAY(db.Float), nullable=True)

    def __init__(self, symbol, date, simulations):
        self.symbol = symbol
        self.date = date
        self.simulations = simulations

    def __repr__(self):
        return '<Simulation {}:{}_{}_{}>'.format(self.id, self.symbol, self.date, self.simulations)

    ...

    def save(self):
        if not self.id:
            db.session.add(self)
        db.session.commit()

    ...

app = create_app()
with app.app_context():
    db.create_all()

[entrypoint.py] 但这不起作用:

from app.probabilities.models import Simulation
from app.auth.models import User
from app import create_app, db

app = create_app()
with app.app_context():
    db.create_all()

这是我的项目结构:

Project
|-- requirements.txt
|-- entrypoint.py
+-- app
    |-- __init__.py
    |-- ... (templates, static...)
    |-- auth
    |   |-- __init__.py
    |   |-- forms.py
    |   |-- models.py
    |   |-- routes.py
    |   +-- templates
    +-- probabilities
        |-- __init__.py
        |-- forms.py
        |-- models.py
        |-- routes.py
        +-- templates

[app/__init__.py] 应用初始化:

from flask import Flask
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
from app.navbars import get_navbars
from decouple import config

login_manager = LoginManager()
db = SQLAlchemy()

bootstrap = Bootstrap()
nav = get_navbars()

def create_app():
    #### [CONFIG FLASK] ####
    app = Flask(__name__)
    app.config['SECRET_KEY'] = config('FLASK_SECRET')
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://{}:{}@{}:{}/{}'.format(
        config('DB_USER'),
        config('DB_PASSWORD'),
        config('DB_HOST'),
        config('DB_PORT'),
        config('DB_DATABASE')
    )
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    #### [CONFIG LOGIN ] ####
    login_manager.init_app(app)
    login_manager.login_view = 'auth.login'

    #### [CONFIG DATABASE] ####
    db.init_app(app)

    #### [CONFIG NAVIGATION BAR] ####
    bootstrap.init_app(app)
    nav.init_app(app)

    #### [BLUEPRINTS] ####
    from .auth import auth_bp
    app.register_blueprint(auth_bp)
    from .probabilities import probabilities_bp
    app.register_blueprint(probabilities_bp)

    return app

两个蓝图都是以类似的方式创建的。例如,这里是“概率”:

[概率/__init__.py]

from flask import Blueprint

probabilities_bp = Blueprint('probabilities', __name__, template_folder='templates')

from . import routes

[概率/models.py]

from app.__init__ import db
import numpy as np

class Simulation(db.Model):

    __tablename__ = 'it_simulation'

    id = db.Column(db.Integer, primary_key=True)
    symbol = db.Column(db.String(10), nullable=False)
    date = db.Column(db.Date(), nullable=False)
    simulations = db.Column(db.Integer(), nullable=False)
    predictions = db.Column(db.ARRAY(db.Float), nullable=True)

    def __init__(self, symbol, date, simulations):
        self.symbol = symbol
        self.date = date
        self.simulations = simulations

    def __repr__(self):
        return '<Simulation {}:{}_{}_{}>'.format(self.id, self.symbol, self.date, self.simulations)

    ...

    def save(self):
        if not self.id:
            db.session.add(self)
        db.session.commit()

    ...

有没有一种方法可以创建表格,而无需在每次我想编辑表格时移动每个模型? flask-migrate 也不检测模型,因此找不到要更新的更改。

我猜有,而且正如我在 Internet 上看到的那样。但此时我无法看到错误。

【问题讨论】:

    标签: python python-3.x flask flask-sqlalchemy python-3.9


    【解决方案1】:

    我不太明白原因,但这似乎是 db 对象的导入问题。

    entrypoint.py 中,db 对象导入为:

    from app import create_app, db
    

    但是models.py 文件都像这样导入它:

    from app.__init__ import db
    

    通过在所有文件中以相同的方式导入db 对象(使用from app import dbfrom app.__init__ import db)来解决。但总是以同样的方式。

    另一种选择是,在entrypoint.py 文件中,从models.py 文件之一导入db

    【讨论】:

      猜你喜欢
      • 2019-03-13
      • 1970-01-01
      • 2018-02-18
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2014-10-15
      • 1970-01-01
      相关资源
      最近更新 更多