【问题标题】:flask-security ImportError: cannot import name 'db'烧瓶安全导入错误:无法导入名称“db”
【发布时间】:2018-09-12 07:14:25
【问题描述】:

我知道这可能是循环导入错误,但我无法找到解决方案。到目前为止,该应用程序非常普通。这是添加了 models.py 的烧瓶安全教程。这是在为项目添加蓝图做准备。

从应用程序导入数据库 ImportError: 无法导入名称 'db'

config.py
run.py
---app
------__init__py
------models.py

运行.py

from app import app

if __name__ == "__main__":
    app.run()

初始化.py

from config import Config
import app.models

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, \
    login_required

db = SQLAlchemy()

# Create app
def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    app.config['DEBUG'] = True
    db.init_app(app)

    user_datastore = SQLAlchemyUserDatastore(db, models.Users,
                                             models.usersRoleNames)
    security = Security(app, user_datastore)

    return app

# Views
@app.route('/')
@login_required
def home():
    return render_template('index.html')

models.py

from app import db
from flask_security import UserMixin, RoleMixin

users_roles = db.Table('users_roles',
        db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('users_role_names.id')))


class usersRoleNames(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))


class Users(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    username = db.Column(db.String(255))
    password = db.Column(db.String(255))
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(100))
    current_login_ip = db.Column(db.String(100))
    login_count = db.Column(db.Integer)
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('usersRoleNames', secondary=users_roles,
                            backref=db.backref('users',
                                               lazy='dynamic'))

【问题讨论】:

    标签: flask flask-security


    【解决方案1】:

    我找到了一个使用 flask-security 的循环导入问题的简单解决方案。当模型跨不同文件声明时,此解决方案特别有用。


    1。创建一个名为models的文件夹:

    我们所有的模型都将保存在这个文件夹中。

    示例文件夹结构可能如下所示

    models/
    ├── _db.py
    ├── __init__.py
    ├── tickets.py
    └── users.py
    
    0 directories, 4 files
    

    2。创建一个名为_db.py的文件:

    在此文件中声明db 对象。

    文件名可以是任何东西,但以下划线开头的文件名可确保在对导入语句进行排序时始终首先导入db 对象。

    ('VS Code 提供了一个自动排序导入的选项,因此使用它不会导致任何问题。')

    _db.py

    from flask_sqlalchemy import SQLAlchemy
    
    db = SQLAlchemy()
    
    

    3。从_db.py文件导入db对象:

    现在我们可以从上面创建的_db.py 文件中导入db 对象:

    users.py

    from ._db import db
    from flask_security import RoleMixin, UserMixin
    
    users_roles = db.Table(
        # Table definition
    )
    
    class usersRoleNames(db.Model, RoleMixin):
        # Table definition
        ...
    
    class Users(db.Model, UserMixin):
        # Table definition
        ...
    

    4。导入__init__.py 文件中的所有内容(可选):

    创建一个 init.py 文件并导入所有模型和其中的db 对象。

    __init__.py

    from ._db import db
    from .tickets import Tickets
    from .users import Users, users_roles, usersRoleNames
    
    '''
    Below part is optional 
    but I like to do it anyways
    '''
    
    __all__ = [
        'db',
        'Tickets',
        'Users',
        'users_roles',
        'usersRoleNames',
    ]
    
    

    通过导入 __init__.py 文件中的所有内容,我们可以直接从模型文件夹中导入。

    所以我们可以这样做

    from .models import db, Tickets, Users
    

    不是这个

    from .models._db import _db
    from .models.tickets import Tickets
    from .models.users import Users
    

    只是一个想法:我不确定以 '下划线' 开头的 python 文件名是否是一种不好的做法。如果您有意见,请分享您的想法。

    【讨论】:

    • 感谢您的回复和发布。我不再使用烧瓶安全,所以我没有能力对此进行测试。这个项目已经迁移到 Vue.js(Nuxt) 作为一个独立的客户端/前端,带有一个独立的烧瓶/后端。但是,站点安全性已被完全重写。不过,我想这对其他人会有所帮助。
    • 很高兴我能帮上忙。
    【解决方案2】:

    尝试在models.py 中声明您的db 对象并将其导入app/__init_.py

    models.py

    from flask_sqlalchemy import SQLAlchemy                                         
    
    db = SQLAlchemy()
    ...
    

    app/__init__.py

    def create_app():                                                               
        app = Flask(__name__)                                                       
        app.config.from_object(Config)                                              
        app.config['DEBUG'] = True                                                  
    
        from app.models import db, Users, usersRoleNames                            
        db.init_app(app)                                                                                                             
    
        user_datastore = SQLAlchemyUserDatastore(db, Users,                         
                                                 usersRoleNames)                    
        security = Security(app, user_datastore)                                    
    
        return app 
    

    【讨论】:

    • 它解决了一个问题并创造了另一个问题。谢谢你的建议。让我解决这部分问题,我会标记它已解决。 users_roles = db.Table('users_roles', AttributeError: type object 'SQLAlchemy' has no attribute 'Table'.
    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2015-12-24
    • 1970-01-01
    相关资源
    最近更新 更多