SQLAlchemy create_all()不创建表

vlju58qv  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(3)|浏览(161)

我试图集成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
我该如何解决这个问题?

l0oc07j2

l0oc07j21#

你应该把你的模型类放在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对象。

snz8szmq

snz8szmq2#

这可能不是为什么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命令时,使用了一个新的app上下文,这意味着使用了一个新的db。此外,在这个世界中,init_db方法中的导入模型不做任何事情,因为它可能是你的模型文件已经被加载(并且与一个单独的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或flak-sqlalchemy,以了解这是否意味着从多个线程向数据库发出的请求是安全的,但是如果您正在阅读本文,您可能也停留在理解这些概念的初级阶段。

6yt4nkrj

6yt4nkrj3#

如果有人在使用专用于每个模型的文件创建表时遇到问题,请注意从一个不同于声明函数的文件中运行“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发布的this thread的答案更好地解释了这一概念

相关问题