Flask中执行db.create_all()遇运行时错误与NameError的解决咨询
问题
跟随Flask教程学习到SQLAlchemy数据库部分,严格按步骤操作后,执行db.create_all()将模型转为数据库表时,终端报运行时错误。参考方案添加app.app_context().push()后,又出现name 'app'未定义的错误。相关代码如下:
# 导入Flask模块 from flask import Flask, render_template # 导入数据库工具 from flask_sqlalchemy import SQLAlchemy # 初始化Flask应用 app = Flask(__name__) # 配置数据库连接地址 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///market.db' # 初始化数据库实例 db = SQLAlchemy(app) # 将应用实例作为参数传入 # 创建数据模型类 class Item(db.Model): # 定义字段:(数据类型(可选长度), 是否允许为空, 是否唯一) # id字段设为主键 id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(length=30), nullable=False, unique=True) price = db.Column(db.Integer(), nullable=False) barcode = db.Column(db.String(length=12), nullable=False, unique=True) description = db.Column(db.String(length=500), nullable=False, unique=True) # 定义主页路由 @app.route('/') # 路由装饰器 def home_page(): return render_template('home.html') # 定义市场页面路由 @app.route('/market') def market(): items = [ {'id': 1, 'name': 'Phone', 'barcode': '893212299897', 'price': '$500'}, {'id': 2, 'name': 'Laptop', 'barcode': '123985473165', 'price': '$900'}, {'id': 3, 'name': 'Keyboard', 'barcode': '231985128446', 'price': '$150'} ] # 第一个参数为HTML模板文件名,后续为传入模板的变量 return render_template('market.html', item_name='Phones', items=items)
解决方案
原因分析
Flask 2.0及以上版本中,数据库操作必须在应用上下文中执行。直接在终端执行db.create_all()时,没有加载应用上下文;而添加app.app_context().push()报错,是因为终端执行时未正确导入app实例。
解决方法
方法1:在代码中自动创建表(开发阶段推荐)
在代码末尾添加逻辑,启动应用时自动创建数据库表:
if __name__ == '__main__': # 进入应用上下文执行创建表操作 with app.app_context(): db.create_all() # 启动Flask应用 app.run(debug=True)
运行脚本后,数据库表会自动生成。
方法2:在Python交互式终端手动创建表
- 进入项目目录,启动Python交互式终端
- 执行以下命令(替换
your_app_file_name为你的脚本文件名,比如app.py):
from your_app_file_name import app, db with app.app_context(): db.create_all()
执行完成后,market.db文件及对应表会生成。
方法3:改用延迟初始化的现代写法(大型项目推荐)
这种方式符合Flask应用工厂模式,从根源避免上下文问题:
from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy # 先初始化数据库实例,暂不传入app db = SQLAlchemy() def create_app(): app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///market.db' # 将应用与数据库实例绑定 db.init_app(app) # 导入模型(若模型在其他文件,需在此导入) from . import models # 创建表(可选,也可在终端执行) with app.app_context(): db.create_all() # 注册路由 @app.route('/') def home_page(): return render_template('home.html') @app.route('/market') def market(): items = [ {'id': 1, 'name': 'Phone', 'barcode': '893212299897', 'price': '$500'}, {'id': 2, 'name': 'Laptop', 'barcode': '123985473165', 'price': '$900'}, {'id': 3, 'name': 'Keyboard', 'barcode': '231985128446', 'price': '$150'} ] return render_template('market.html', item_name='Phones', items=items) return app
之后可通过flask run启动应用,或在终端导入create_app()获取上下文后创建表。
内容的提问来源于stack exchange,提问作者Erick Pruneda
相关产品推荐
相关产品推荐

