Flask中使用flask-sqlalchemy时db.create_all()无法创建表

如题,我在学习《Flask Web开发:基于Python的Web应用开发实战》这本书第七章的时候,在shell中使用db.create_all()创建sqlite数据库。但是发现这个命令只能创建出sqlite文件,不能创建数据库table

(venv) FlaskStudy$ python manage.py shell
>>> from app import db
>>> db.create_all()

几次尝试过后,发现如果在执行db.create_all()前导入我创建的数据库模型,就能正常的创建出表了:

(venv) FlaskStudy$ python manage.py shell
>>> from app import db
>>> from app.models import User, Role
>>> db.create_all()

或者在manage.py中导入数据库模型也可以:

import os
from app import create_app, db
# 就是这一句
from app.models import User, Role
from flask.ext.script import Manager, Shell
from flask.ext.migrate import Migrate, MigrateCommand

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)
migrate = Migrate(app, db)

manager.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manager.run()

这是什么原理呢?求大神给讲解一下。

阅读 21.7k
6 个回答

SQLAlchemy 的实现,可以看到 Model 是一个元类,在继承这个类来声明子类的时候,会把表模型注册到 sqlalchemy 里,所以在 create_all 之前必须把模型的声明导入进来。

(venv) FlaskStudy$ python manage.py shell

from app import db
db.create_all()

要看你的manage有没有引入model相关的db进入到当前的contex,看你的代码,明显没有木有
正常来说都要如下写法就ok了

# Migration commands
manager.add_command('db', MigrateCommand)


# Add interactive project shell
def make_shell_context():
    return dict(app=current_app, db=db)
manager.add_command("shell", Shell(make_context=make_shell_context))

make_shell_context: 就是启动Shell时,默认加载db,app(falsk相关的web运行context),要不然shell不会跟踪到

模型就是表结构,不告诉db,db难道能猜出嘛。

预计是没绑定到对应的Sqlalchemy模型。一般使用db.create_all()都可以生成数据库文件及其定义的表的

刚刚看完第7章。我感觉你的manager.py有点问题,缺少shell上下文,所以说你打开的就是一个普通的shell, 并不可以直接使用 app里面的变量,必须手动import。 可以看看下面的代码,加上那几行代码就可以直接使用了。

#!/usr/bin/env python

from app import create_app, db
from app.models import User, Role
from flask.ext.script import Manager, Shell

app = create_app()
manager = Manager(app)


def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)

manager.add_command("shell", Shell(make_context=make_shell_context))
if __name__ == '__main__':
    manager.run()

我试了,并不需要引入models,只需要将create_all()编程create_all(app=app)即可或者

with app.app_context():
    db.create_all()
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏