SQLAlchemy未创建表

时间:2019-01-09 20:52:29

标签: python sqlalchemy

我试图像教程中那样设置数据库,但是遇到编程错误,即当我尝试添加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。

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

2 个答案:

答案 0 :(得分:0)

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

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

Python调用正在执行的模块'__main__',因为您在模块底部具有if __name__ == '__main__'条件,所以您会知道。因此,创建的第一个Base__main__.Base。然后,在models.py中,from database import Base导致database模块被再次解析,在命名空间中创建database.Base,这就是{{ 1}}继承。然后回到BaseUser调用正在使用database.py中的元数据,其中没有表,因此什么也不创建。

不要在创建Base.metadata.create_all(bind=engine)实例的模块之外执行。创建另一个名为__main__.Base(或任何其他名称)的模块,然后在其中移动Base函数,并将main.py中的init_db()Basedb_session导入engine。这样,您将始终使用相同的database.py实例。这是main.py的示例:

Base

答案 1 :(得分:0)

  • 一次声明基类(对于每个数据库)并将其导入定义表类的所有模块(从Base继承)
  • 要让Base(元类)扫描并找出从其继承的所有类,我们需要将定义了此类表类(从Base继承)的所有模块导入到我们称为Metadata.create_all(engine的模块)中。 )。