我正在尝试像在教程中一样设置数据库,但是当我尝试添加 User 时遇到一个表不存在的编程错误

这是出错的文件( 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()

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

这是 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)

我试过了:
  • 在添加用户之前提交(在 create_all 之后)
  • 从数据库中删除现有表(尽管该表似乎从未被提交)
  • from models import User 而不是 import models(在 create_all 之前)

  • 对不起,如果有这么多类似的问题,我保证我会寻找答案,但我确定我没有犯过(或至少是我看到的那些)总是愚蠢的错误。

    我正在使用 MariaDB。

    对不起,很长的帖子,非常感谢提前。

    最佳答案

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

    一个简单的测试是将 print('creating Base') 函数调用放在 Base = declarative_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 导入 o​​jit_code 。这样,您始终使用相同的 main.py 实例。这是 Base 的示例:

    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()
    

    关于python - SQLAlchemy 不创建表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54118182/

    10-16 22:16