我正在使用 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。
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
...
我不明白这里的差异。
你的问题是你有两个独立的
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)