Flask-SQLAlchemy db.create_all() 在应用程序上下文之外工作会引发 RuntimeError

问题描述 投票:0回答:4

我最近更新了 Flask-SQLAlchemy,现在

db.create_all
正在提高
RuntimeError: working outside of application context
。怎么打电话给
create_all

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///project.db'
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)

db.create_all()

这会引发以下错误:

Traceback (most recent call last):
  File "/home/david/Projects/flask-sqlalchemy/example.py", line 11, in <module>
    db.create_all()
  File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 751, in create_all
    self._call_for_binds(bind_key, "create_all")
  File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 722, in _call_for_binds
    engine = self.engines[key]
  File "/home/david/Projects/flask-sqlalchemy/src/flask_sqlalchemy/extension.py", line 583, in engines
    app = current_app._get_current_object()  # type: ignore[attr-defined]
  File "/home/david/Projects/flask-sqlalchemy/.venv/lib/python3.10/site-packages/werkzeug/local.py", line 513, in _get_current_object
    raise RuntimeError(unbound_message) from None
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
python flask flask-sqlalchemy
4个回答
64
投票

从 Flask-SQLAlchemy 3.0 开始,对

db.engine
(和
db.session
)的所有访问都需要活动的 Flask 应用程序上下文。
db.create_all
使用
db.engine
,因此它需要应用程序上下文。

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

当 Flask 处理请求或运行 CLI 命令时,会自动推送上下文。在这些情况之外,您只需手动推送一个,例如在设置应用程序时。


您也可以在 shell 中手动调用它,而不是在代码中调用

create_all
。使用
flask shell
启动已具有应用程序上下文并导入
db
对象的 Python shell。

$ flask shell
>>> db.create_all()

或者如果使用普通的

python
shell,则手动推送上下文。

$ python
>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()

6
投票

这是一个

example.py
,它配置 SQLite 数据库、模型,然后创建数据库。
with app.app_context()
周围的
db.create_all()
线是避免上下文错误所需的。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///project.db"
db = SQLAlchemy()

class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String)
    body = db.Column(db.String)

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

使用此命令运行开发服务器,如果数据库不存在,则会创建数据库。

$ flask -A example.py --debug run

3
投票

如果您使用

python
shell 而不是
flask shell
,则可以手动推送上下文。
flask shell
将为您处理。

>>> from project import app, db
>>> app.app_context().push()
>>> db.create_all()

Flask 文档此视频中了解有关应用程序上下文的更多信息。


0
投票

对我来说,我只需附加“app.app_context().push()”即可! 请参阅下面的完整代码:

basic.py 是文件名。

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)

app.app_context().push()

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join('data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Person(db.Model):

    # Manual Table Name Choice
    __tablename__ = 'puppies'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)
    age = db.Column(db.Integer)

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person {self.name} is {self.age} Yea/s Old"

setupdatabase.py是执行文件的名称。

from basic import db, Person

db.create_all()

demo1 = Puppy('Eva', 30)
demo2 = Puppy('kawsar', 40)

db.session.add_all([demo1, demo2])
db.session.commit()
© www.soinside.com 2019 - 2024. All rights reserved.