SQLAlchemy 不创建表

SQLAlchemy not creating tables

我正在尝试像在教程中那样设置数据库,但是当我尝试添加 User[= 时,出现了一个编程错误,提示 table 不存在19=]

这是错误的文件 (database.py):

from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine(
    "mysql+pymysql://testuser:testpassword@localhost/test?charset=utf8",
    connect_args = {
        "port": 3306
    },
    echo="debug",
    echo_pool=True
)

db_session = scoped_session(
    sessionmaker(
        bind=engine,
        autocommit=False,
        autoflush=False
    )
)

Base = declarative_base()

def init_db():
    import models
    Base.metadata.create_all(bind=engine)

    from models import User
    db_session.add(
        User(username="testuser", password_hash=b"", password_salt=b"", balance=1)
    )
    db_session.commit()

    print("Initialized the db")


if __name__ == "__main__":
    init_db()

要初始化数据库(创建 tables)我只是 运行 文件。 创建测试用户时出错。

这里是models.py:

from sqlalchemy import Column, Integer, Numeric, Binary, String
from sqlalchemy.orm import relationship

from database import Base


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)

    username = Column(String(16), unique=True)
    password_hash = Column(Binary(32))
    password_salt = Column(Binary(32))

    balance = Column(Numeric(precision=65, scale=8))

    def __repr__(self):
        return "<User(balance={})>".format(balance)

我试过了:

抱歉,如果有这么多类似的问题,我保证我已经搜索过答案,但我确保我没有犯(或至少我看到的那些)总是愚蠢的错误。

我正在使用 MariaDB。

很抱歉post,非常感谢。

database.py 中的 Base 与导入 models.pyBase 不同。

一个简单的测试是在 Base = declarative_base() 语句的正上方放置一个 print('creating Base') 函数调用,您会看到它被创建了两次。

Python 调用正在执行的模块 '__main__',因为模块底部有 if __name__ == '__main__' 条件。所以创建的第一个 Base__main__.Base。然后,在 models.py 中,from database import Base 导致 database 模块再次被解析,在命名空间中创建 database.Base,也就是 Base 来自 User继承。然后回到 database.pyBase.metadata.create_all(bind=engine) 调用正在使用来自 __main__.Base 的元数据,其中没有表,因此不会创建任何内容。

不要执行创建 Base 实例的模块。创建另一个名为 main.py(或其他)的模块,然后将 init_db() 函数移到那里并将 Basedb_sessionenginedatabase.py 导入到main.py。这样,您始终使用相同的 Base 实例。这是 main.py:

的例子
from database import Base, db_session, engine
from models import User


def init_db():

    Base.metadata.create_all(bind=engine)

    db_session.add(
        User(username="testuser", password_hash=b"", password_salt=b"", balance=1)
    )
    db_session.commit()

    print("Initialized the db")


if __name__ == "__main__":
    init_db()
  • 声明 Base class 一次(对于每个数据库)并将其导入到定义 table classes(继承自 Base)的所有模块
  • 为了使 Base (a metaclass) 扫描并找出所有继承自它的 classes,我们需要导入所有模块,其中 table classes(继承自 Base)被定义到我们调用 Metadata.create_all(engine).
  • 的模块