Flask-SQLAlchemy 表在模式中定义,但未创建[重复]

问题描述 投票:0回答:1

我正在使用 Flask 创建我的第一个简单的 RBAC 登录/注册页面

这是我的项目结构

├── app.py
├── flask_api
│   ├── __init__.py
│   ├── config.py
│   ├── extensions.py
│   ├── models.py
│   └── routes.py
├── instance
└── migrations
    ├── __pycache__
    ├── env.py
    └── versions

app.py

from flask_api import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

__init__.py

from flask import Flask
from flask_api.config import Config
from flask_api.extensions import db, migrate, init_extensions, user_datastore
from flask_api.routes import main

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    init_extensions(app) # Initializing extensions
    app.register_blueprint(main) # Registering blueprint
    return app

if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

扩展.py

from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore
from flask_migrate import Migrate
from flask_api.models import User, Role

db = SQLAlchemy()
migrate = Migrate()
user_datastore = SQLAlchemyUserDatastore(db, User, Role)

def init_extensions(app):
    global user_datastore, security
    db.init_app(app)
    migrate.init_app(app, db)
    security = Security(app, user_datastore)

模型.py

from flask_sqlalchemy import SQLAlchemy
from flask_security import UserMixin, RoleMixin

db = SQLAlchemy()

roles_users = db.Table('roles_users',
    db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
    db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)

class Role(db.Model, RoleMixin):
    ...

class User(db.Model, UserMixin):
    ...

routes.py

from flask import Blueprint, request, jsonify
from flask_api.models import db, User, Role
from flask_api.extensions import user_datastore

main = Blueprint('main', __name__)

@main.route('/user-signup', methods=['POST'])
def user_signup():
    data = request.json
    if user_datastore.find_user(email=data['email']):
        return jsonify(message="Email is already registered"), 400
    # More signup logic is there
    ...

@main.route('/user-login', methods=['POST'])
def user_login():
    # More logic
    ...


现在,当我使用 flask run 运行

app.py
时 并向
/user-signup
端点发出 POST 请求,
main.db
被创建,但其中没有表。

我知道我必须在某处使用这行代码来手动启动表:

with app.app_context():
    db.create_all()

但是我真的无法完全思考这个问题,即该行代码应该放在哪里。这些是我尝试过的几种方法,但它们都不成功

  • 创建app = create_app()后尝试将其放入
    app.py
  • 初始化扩展后,尝试将 init.py 放入
    create_app()
    方法中。
  • 尝试将其放入init_extensions(app)方法中的
    extensions.py
    中。

每一个都不起作用

有人可以指导我在这里做错了什么,以及如果可能的话更好的设计方法。

PS - 我隐藏了一些代码,因为我认为它与问题无关,但如果你想查看它,我可以稍后编辑我的问题!

编辑 - 另一件事,如果我放弃我的项目结构,并将所有内容保留在一个文件中(__init__.py),那么它就可以正常工作,表可以完美地自行创建(甚至不需要

db.create_all()
) 。
这就是为什么我坚信我当前的项目结构是可能的。

编辑2 - 我更新了 __init__.py 如下:

from flask import Flask
from flask_api.config import Config
from flask_api.extensions import db, migrate, init_extensions, user_datastore
from flask_api.routes import main

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    with app.app_context():
        init_extensions(app) 
        app.register_blueprint(main) 
        print(db.metadata.tables.keys()) # dict_keys([])
        print(db.engine.table_names())   # ['alembic_version']
        db.create_all()
        return app

if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

因此,即使表元数据也不存在,并且此处执行

db.create_all()
也不会执行任何操作。

在我的routes.py中我用这些进行了测试 -

from flask import Blueprint, request, jsonify
from flask_api.models import db, User, Role
from flask_api.extensions import user_datastore

main = Blueprint('main', __name__)

@main.route('/user-signup', methods=['POST'])
def user_signup():
    print(db.metadata.tables.keys()) # dict_keys(['roles_users', 'role', 'user'])
    print(db.engine.table_names())   # ['alembic_version']
    import pdb; pdb.set_trace() # To stop further code from executing
    # More signup logic is there
    ...

@main.route('/user-login', methods=['POST'])
def user_login():
    # More logic
    ...

我不明白这里的差异。

python sqlite flask flask-sqlalchemy rbac
1个回答
0
投票

你的问题是你有两个独立的

db = SQLAlchemy()
彼此没有连接。 在
extensions.py
中,您应该将
User
Role
db
一起导入,因为
db
实例实际上具有为其声明的
Role
User
模型,而
extensions.py
中定义的模型具有都没有。 简而言之,以下是您所做工作的补丁,应该解决以下问题:将所有内容放在同一个文件中可以工作,而您的拆分版本则不能,因为拆分版本存在此缺陷,其中存在重复的
db
定义了用来创建数据库的参数。

--- a/extensions.py
+++ b/extensions.py
@@ -1,9 +1,8 @@
 from flask_sqlalchemy import SQLAlchemy
 from flask_security import Security, SQLAlchemyUserDatastore
 from flask_migrate import Migrate
-from flask_api.models import User, Role
+from flask_api.models import db, User, Role
 
-db = SQLAlchemy()
 migrate = Migrate()
 user_datastore = SQLAlchemyUserDatastore(db, User, Role)
 
© www.soinside.com 2019 - 2024. All rights reserved.