SQLAlchemy create_all() 没有创建表
- 2025-03-18 08:56:00
- admin 原创
- 65
问题描述:
我正在尝试集成 PostgreSQL 和 SQLAlchemy,但 SQLAlchemy.create_all() 并未从我的模型中创建任何表。
我的代码:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass@localhost/flask_app'
db = SQLAlchemy(app)
db.create_all()
db.session.commit()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
admin = User('admin', 'admin@example.com')
guest = User('guest', 'guest@example.com')
db.session.add(admin)
db.session.add(guest)
db.session.commit()
users = User.query.all()
print users
但是我收到此错误:sqlalchemy.exc.ProgrammingError: (ProgrammingError) relation "user" does not exist
我该如何修复此问题?
解决方案 1:
您应该将模型类放在create_all()
调用之前,如下所示:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass@localhost/flask_app'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, username, email):
self.username = username
self.email = email
def __repr__(self):
return '<User %r>' % self.username
with app.app_context():
db.create_all()
db.session.add(User('admin', 'admin@example.com'))
db.session.add(User('guest', 'guest@example.com'))
db.session.commit()
users = User.query.all()
print(users)
如果您的模型在单独的模块中声明,请在调用之前导入它们create_all()
。
假设User
模型位于一个名为的文件中models.py
,
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass@localhost/flask_app'
db = SQLAlchemy(app)
# See important note below
from models import User
with app.app_context():
db.create_all()
db.session.add(User('admin', 'admin@example.com'))
db.session.add(User('guest', 'guest@example.com'))
db.session.commit()
users = User.query.all()
print(users)
重要提示:初始化对象后导入模型非常重要db
,因为您还需要从该模块models.py
导入对象。db
解决方案 2:
如果有人在使用专用于每个模型的文件创建表时遇到问题,请注意从与声明该函数的文件不同的文件运行“create_all”函数。因此,如果文件系统是这样的:
Root
--app.py <-- file from which app will be run
--models
----user.py <-- file with "User" model
----order.py <-- file with "Order" model
----database.py <-- file with database and "create_all" function declaration
从 app.py 调用“create_all”函数时要小心。
@SuperShoot发布的此主题的答案更好地解释了这个概念
解决方案 3:
这可能不是方法调用对人们不起作用的主要原因create_all()
,但对我来说,来自各种教程的拼凑的说明使得我在请求上下文中创建我的数据库,这意味着我有类似的东西:
# lib/db.py
from flask import g, current_app
from flask_sqlalchemy import SQLAlchemy
def get_db():
if 'db' not in g:
g.db = SQLAlchemy(current_app)
return g.db
我还有一个单独的 cli 命令,它也执行 create_all 操作:
# tasks/db.py
from lib.db import get_db
@current_app.cli.command('init-db')
def init_db():
db = get_db()
db.create_all()
我也正在使用应用程序工厂。
运行 cli 命令时,将使用新的应用程序上下文,这意味着将使用新的数据库。此外,在这个世界中,init_db 方法中的导入模型不会执行任何操作,因为您的模型文件可能已加载(并与单独的数据库相关联)。
我想到的一个解决办法是确保数据库是一个单一的全局引用:
# lib/db.py
from flask import g, current_app
from flask_sqlalchemy import SQLAlchemy
db = None
def get_db():
global db
if not db:
db = SQLAlchemy(current_app)
return db
我还没有深入研究 flask、sqlalchemy 或 flask-sqlalchemy 来了解这是否意味着从多个线程向数据库发出的请求是安全的,但如果您正在阅读本文,您可能也处于理解这些概念的初级阶段。
解决方案 4:
我在 db.py 文件中使用了上述信息,如下所示。我发现创建单独的 app.py、db.py 和 server.py 文件以避免循环依赖很重要。
from flask_sqlalchemy import SQLAlchemy
from app import app
from werkzeug.security import generate_password_hash
db = SQLAlchemy(app)
#
# The models need to be imported after the db is initialized.
#
from models.user import User
from models.video_attributes import VideoAttributes
from models.model_development import ModelDevelopment
with app.app_context() as ctx:
ctx.push()
db.create_all()
# Check for existing users
if User.query.count() == 0:
# Create first user as admin
db.session.add(User(login="admin", password=generate_password_hash("admin")))
db.session.commit()
扫码咨询,免费领取项目管理大礼包!